@@ -35,6 +35,7 @@ import (
3535 "sigs.k8s.io/cluster-api/feature"
3636 "sigs.k8s.io/cluster-api/internal/contract"
3737 "sigs.k8s.io/cluster-api/internal/controllers/topology/cluster/scope"
38+ "sigs.k8s.io/cluster-api/internal/hooks"
3839 tlog "sigs.k8s.io/cluster-api/internal/log"
3940 runtimecatalog "sigs.k8s.io/cluster-api/internal/runtime/catalog"
4041)
@@ -313,6 +314,37 @@ func (r *Reconciler) computeControlPlaneVersion(ctx context.Context, s *scope.Sc
313314 // Nb. We do not return early in the function if the control plane is already at the desired version so as
314315 // to know if the control plane is being upgraded. This information
315316 // is required when updating the TopologyReconciled condition on the cluster.
317+
318+ // Call the AfterControlPlaneUpgrade now that the control plane is upgraded.
319+ if feature .Gates .Enabled (feature .RuntimeSDK ) {
320+ // Call the hook only if we are tracking the intent to do so. If it is not tracked it means we don't need to call the
321+ // hook because we didn't go through an upgrade or we already called the hook after the upgrade.
322+ if hooks .IsPending (runtimehooksv1 .AfterControlPlaneUpgrade , s .Current .Cluster ) {
323+ // Call all the registered extension for the hook.
324+ hookRequest := & runtimehooksv1.AfterControlPlaneUpgradeRequest {
325+ Cluster : * s .Current .Cluster ,
326+ KubernetesVersion : desiredVersion ,
327+ }
328+ hookResponse := & runtimehooksv1.AfterControlPlaneUpgradeResponse {}
329+ if err := r .RuntimeClient .CallAllExtensions (ctx , runtimehooksv1 .AfterControlPlaneUpgrade , s .Current .Cluster , hookRequest , hookResponse ); err != nil {
330+ return "" , errors .Wrapf (err , "error calling the %s hook" , runtimecatalog .HookName (runtimehooksv1 .AfterControlPlaneUpgrade ))
331+ }
332+ // Add the response to the tracker so we can later update condition or requeue when required.
333+ s .HookResponseTracker .Add (runtimehooksv1 .AfterControlPlaneUpgrade , hookResponse )
334+
335+ // If the extension responds to hold off on starting Machine deployments upgrades,
336+ // change the UpgradeTracker accordingly, otherwise the hook call is completed and we
337+ // can remove this hook from the list of pending-hooks.
338+ if hookResponse .RetryAfterSeconds != 0 {
339+ s .UpgradeTracker .MachineDeployments .HoldUpgrades (true )
340+ } else {
341+ if err := hooks .MarkAsDone (ctx , r .Client , s .Current .Cluster , runtimehooksv1 .AfterControlPlaneUpgrade ); err != nil {
342+ return "" , errors .Wrapf (err , "failed to remove the %s hook from pending hooks tracker" , runtimecatalog .HookName (runtimehooksv1 .AfterControlPlaneUpgrade ))
343+ }
344+ }
345+ }
346+ }
347+
316348 return * currentVersion , nil
317349 }
318350
@@ -349,14 +381,21 @@ func (r *Reconciler) computeControlPlaneVersion(ctx context.Context, s *scope.Sc
349381 if err := r .RuntimeClient .CallAllExtensions (ctx , runtimehooksv1 .BeforeClusterUpgrade , s .Current .Cluster , hookRequest , hookResponse ); err != nil {
350382 return "" , errors .Wrapf (err , "failed to call %s hook" , runtimecatalog .HookName (runtimehooksv1 .BeforeClusterUpgrade ))
351383 }
384+ // Add the response to the tracker so we can later update condition or requeue when required.
352385 s .HookResponseTracker .Add (runtimehooksv1 .BeforeClusterUpgrade , hookResponse )
353386 if hookResponse .RetryAfterSeconds != 0 {
354387 // Cannot pickup the new version right now. Need to try again later.
355388 return * currentVersion , nil
356389 }
390+
391+ // We are picking up the new version here.
392+ // Track the intent of calling the AfterControlPlaneUpgrade and the AfterClusterUpgrade hooks once we are done with the upgrade.
393+ if err := hooks .MarkAsPending (ctx , r .Client , s .Current .Cluster , runtimehooksv1 .AfterControlPlaneUpgrade , runtimehooksv1 .AfterClusterUpgrade ); err != nil {
394+ return "" , errors .Wrapf (err , "failed to mark the %s hook as pending" , []string {runtimecatalog .HookName (runtimehooksv1 .AfterControlPlaneUpgrade ), runtimecatalog .HookName (runtimehooksv1 .AfterClusterUpgrade )})
395+ }
357396 }
358397
359- // Control plane and machine deployments are stable.
398+ // Control plane and machine deployments are stable. All the required hook are called.
360399 // Ready to pick up the topology version.
361400 return desiredVersion , nil
362401}
0 commit comments