@@ -29,6 +29,7 @@ import (
2929 kerrors "k8s.io/apimachinery/pkg/util/errors"
3030 "k8s.io/klog/v2"
3131 ctrl "sigs.k8s.io/controller-runtime"
32+ "sigs.k8s.io/controller-runtime/pkg/client"
3233
3334 clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2"
3435 runtimehooksv1 "sigs.k8s.io/cluster-api/api/runtime/hooks/v1alpha1"
@@ -48,14 +49,16 @@ type Engine interface {
4849}
4950
5051// NewEngine creates a new patch engine.
51- func NewEngine (runtimeClient runtimeclient.Client ) Engine {
52+ func NewEngine (c client. Client , runtimeClient runtimeclient.Client ) Engine {
5253 return & engine {
54+ client : c ,
5355 runtimeClient : runtimeClient ,
5456 }
5557}
5658
5759// engine implements the Engine interface.
5860type engine struct {
61+ client client.Client
5962 runtimeClient runtimeclient.Client
6063}
6164
@@ -73,8 +76,14 @@ func (e *engine) Apply(ctx context.Context, blueprint *scope.ClusterBlueprint, d
7376
7477 log := ctrl .LoggerFrom (ctx )
7578
79+ // Determine contract version used by the ControlPlane.
80+ controlPlaneContractVersion , err := contract .GetContractVersionForVersion (ctx , e .client , desired .ControlPlane .Object .GroupVersionKind ().GroupKind (), desired .ControlPlane .Object .GroupVersionKind ().Version )
81+ if err != nil {
82+ return errors .Wrapf (err , "failed to generate patch request: failed to get contract version for the ControlPlane object" )
83+ }
84+
7685 // Create a patch generation request.
77- req , err := createRequest (blueprint , desired )
86+ req , err := createRequest (blueprint , desired , controlPlaneContractVersion )
7887 if err != nil {
7988 return errors .Wrapf (err , "failed to generate patch request" )
8089 }
@@ -91,7 +100,7 @@ func (e *engine) Apply(ctx context.Context, blueprint *scope.ClusterBlueprint, d
91100 if clusterClassPatch .External == nil {
92101 definitionFrom = clusterv1 .VariableDefinitionFromInline
93102 }
94- if err := addVariablesForPatch (blueprint , desired , req , definitionFrom ); err != nil {
103+ if err := addVariablesForPatch (blueprint , desired , req , definitionFrom , controlPlaneContractVersion ); err != nil {
95104 return errors .Wrapf (err , "failed to calculate variables for patch %q" , clusterClassPatch .Name )
96105 }
97106 log .V (5 ).Info ("Applying patch to templates" )
@@ -144,15 +153,15 @@ func (e *engine) Apply(ctx context.Context, blueprint *scope.ClusterBlueprint, d
144153
145154 // Use patched templates to update the desired state objects.
146155 log .V (5 ).Info ("Applying patched templates to desired state" )
147- if err := updateDesiredState (ctx , req , blueprint , desired ); err != nil {
156+ if err := updateDesiredState (ctx , req , blueprint , desired , controlPlaneContractVersion ); err != nil {
148157 return errors .Wrapf (err , "failed to apply patches to desired state" )
149158 }
150159
151160 return nil
152161}
153162
154163// addVariablesForPatch adds variables for a given ClusterClassPatch to the items in the PatchRequest.
155- func addVariablesForPatch (blueprint * scope.ClusterBlueprint , desired * scope.ClusterState , req * runtimehooksv1.GeneratePatchesRequest , definitionFrom string ) error {
164+ func addVariablesForPatch (blueprint * scope.ClusterBlueprint , desired * scope.ClusterState , req * runtimehooksv1.GeneratePatchesRequest , definitionFrom , controlPlaneContractVersion string ) error {
156165 // If there is no definitionFrom return an error.
157166 if definitionFrom == "" {
158167 return errors .New ("failed to calculate variables: no patch name provided" )
@@ -187,7 +196,7 @@ func addVariablesForPatch(blueprint *scope.ClusterBlueprint, desired *scope.Clus
187196 }
188197 // If the item holder reference is a Control Plane machine add the Control Plane variables.
189198 if blueprint .HasControlPlaneInfrastructureMachine () &&
190- item .HolderReference .FieldPath == strings . Join ( contract . ControlPlane (). MachineTemplate (). InfrastructureRef (). Path (), "." ) {
199+ item .HolderReference .FieldPath == getControlPlaneHolderFieldPath ( controlPlaneContractVersion ) {
191200 item .Variables = controlPlaneVariables
192201 }
193202 // If the item holder reference is a MachineDeployment calculate the variables for each MachineDeploymentTopology
@@ -261,7 +270,7 @@ func getMPTopologyFromMP(blueprint *scope.ClusterBlueprint, mp *clusterv1.Machin
261270// replicas of a MachineDeployment.
262271// NOTE: A single GeneratePatchesRequest object is used to carry templates state across subsequent Generate calls.
263272// NOTE: This function does not add variables to items for the request, as the variables depend on the specific patch.
264- func createRequest (blueprint * scope.ClusterBlueprint , desired * scope.ClusterState ) (* runtimehooksv1.GeneratePatchesRequest , error ) {
273+ func createRequest (blueprint * scope.ClusterBlueprint , desired * scope.ClusterState , controlPlaneContractVersion string ) (* runtimehooksv1.GeneratePatchesRequest , error ) {
265274 req := & runtimehooksv1.GeneratePatchesRequest {}
266275
267276 // Add the InfrastructureClusterTemplate.
@@ -288,7 +297,7 @@ func createRequest(blueprint *scope.ClusterBlueprint, desired *scope.ClusterStat
288297 // add the InfrastructureMachineTemplate for control plane machines.
289298 if blueprint .HasControlPlaneInfrastructureMachine () {
290299 t , err := newRequestItemBuilder (blueprint .ControlPlane .InfrastructureMachineTemplate ).
291- WithHolder (desired .ControlPlane .Object , desired .ControlPlane .Object .GroupVersionKind (), strings . Join ( contract . ControlPlane (). MachineTemplate (). InfrastructureRef (). Path (), "." )).
300+ WithHolder (desired .ControlPlane .Object , desired .ControlPlane .Object .GroupVersionKind (), getControlPlaneHolderFieldPath ( controlPlaneContractVersion )).
292301 Build ()
293302 if err != nil {
294303 return nil , errors .Wrapf (err , "failed to prepare ControlPlane's %s %s for patching" ,
@@ -523,7 +532,7 @@ func convertToValidationRequest(generateRequest *runtimehooksv1.GeneratePatchesR
523532
524533// updateDesiredState uses the patched templates of a GeneratePatchesRequest to update the desired state.
525534// NOTE: This func should be called after all the patches have been applied to the GeneratePatchesRequest.
526- func updateDesiredState (ctx context.Context , req * runtimehooksv1.GeneratePatchesRequest , blueprint * scope.ClusterBlueprint , desired * scope.ClusterState ) error {
535+ func updateDesiredState (ctx context.Context , req * runtimehooksv1.GeneratePatchesRequest , blueprint * scope.ClusterBlueprint , desired * scope.ClusterState , controlPlaneContractVersion string ) error {
527536 var err error
528537
529538 // Update the InfrastructureCluster.
@@ -563,7 +572,7 @@ func updateDesiredState(ctx context.Context, req *runtimehooksv1.GeneratePatches
563572 // If the ClusterClass mandates the ControlPlane has InfrastructureMachines,
564573 // update the InfrastructureMachineTemplate for ControlPlane machines.
565574 if blueprint .HasControlPlaneInfrastructureMachine () {
566- infrastructureMachineTemplate , err := getTemplateAsUnstructured (req , desired .ControlPlane .Object .GetKind (), strings . Join ( contract . ControlPlane (). MachineTemplate (). InfrastructureRef (). Path (), "." ), requestTopologyName {})
575+ infrastructureMachineTemplate , err := getTemplateAsUnstructured (req , desired .ControlPlane .Object .GetKind (), getControlPlaneHolderFieldPath ( controlPlaneContractVersion ), requestTopologyName {})
567576 if err != nil {
568577 return err
569578 }
@@ -631,3 +640,10 @@ func definitionsForPatch(blueprint *scope.ClusterBlueprint, definitionFrom strin
631640 }
632641 return variableDefinitionsForPatch
633642}
643+
644+ func getControlPlaneHolderFieldPath (contractVersion string ) string {
645+ if contractVersion == "v1beta1" {
646+ return strings .Join (contract .ControlPlane ().MachineTemplate ().InfrastructureV1Beta1Ref ().Path (), "." )
647+ }
648+ return strings .Join (contract .ControlPlane ().MachineTemplate ().InfrastructureRef ().Path (), "." )
649+ }
0 commit comments