@@ -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,33 @@ 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+ // Let's call the AfterControlPlaneUpgrade now that the control plane is upgraded.
319+ if feature .Gates .Enabled (feature .RuntimeSDK ) {
320+ // Call the hook only if it is marked. If it is not marked it means we don't need ot 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+ hookRequest := & runtimehooksv1.AfterControlPlaneUpgradeRequest {
324+ Cluster : * s .Current .Cluster ,
325+ KubernetesVersion : desiredVersion ,
326+ }
327+ hookResponse := & runtimehooksv1.AfterControlPlaneUpgradeResponse {}
328+ if err := r .RuntimeClient .CallAllExtensions (ctx , runtimehooksv1 .AfterControlPlaneUpgrade , s .Current .Cluster , hookRequest , hookResponse ); err != nil {
329+ return "" , errors .Wrapf (err , "error calling the %s hook" , runtimecatalog .HookName (runtimehooksv1 .AfterControlPlaneUpgrade ))
330+ }
331+ s .HookResponseTracker .Add (runtimehooksv1 .AfterControlPlaneUpgrade , hookResponse )
332+ if hookResponse .RetryAfterSeconds != 0 {
333+ // We have to block the upgrade of the Machine deployments.
334+ s .UpgradeTracker .MachineDeployments .HoldUpgrades (true )
335+ } else {
336+ // We are done with the hook for now. We don't need to call it anymore. Unmark it.
337+ if err := hooks .MarkAsDone (ctx , r .Client , s .Current .Cluster , runtimehooksv1 .AfterControlPlaneUpgrade ); err != nil {
338+ return "" , errors .Wrapf (err , "failed to unmark the %s hook" , runtimecatalog .HookName (runtimehooksv1 .AfterControlPlaneUpgrade ))
339+ }
340+ }
341+ }
342+ }
343+
316344 return * currentVersion , nil
317345 }
318346
@@ -354,9 +382,15 @@ func (r *Reconciler) computeControlPlaneVersion(ctx context.Context, s *scope.Sc
354382 // Cannot pickup the new version right now. Need to try again later.
355383 return * currentVersion , nil
356384 }
385+
386+ // We are picking up the new version here.
387+ // Mark the AfterControlPlaneUpgrade and the AfterClusterUpgrade hooks so that we call them once we are done with the upgrade.
388+ if err := hooks .MarkAsPending (ctx , r .Client , s .Current .Cluster , runtimehooksv1 .AfterControlPlaneUpgrade , runtimehooksv1 .AfterClusterUpgrade ); err != nil {
389+ return "" , errors .Wrapf (err , "failed to mark the %s hook" , []string {runtimecatalog .HookName (runtimehooksv1 .AfterControlPlaneUpgrade ), runtimecatalog .HookName (runtimehooksv1 .AfterClusterUpgrade )})
390+ }
357391 }
358392
359- // Control plane and machine deployments are stable.
393+ // Control plane and machine deployments are stable. All the required hook are called.
360394 // Ready to pick up the topology version.
361395 return desiredVersion , nil
362396}
0 commit comments