From ed56a4acc11557dc03bb60f3963afd2a484b38a3 Mon Sep 17 00:00:00 2001
From: Emilien Macchi <emacchi@redhat.com>
Date: Tue, 28 Jan 2025 15:42:21 -0500
Subject: [PATCH] OpenStackMachine: add OpenStackServerRef to Status

An `OpenStackMachine` object has now its `OpenStackServerRef` in Status
so we can know to with `OpenStackServer` it's attached to.

We will set that ref as soon as we found an existing object, whether the
server is running or not yet or in error state.
---
 api/v1beta1/openstackmachine_types.go         |  5 ++++
 api/v1beta1/zz_generated.deepcopy.go          |  5 ++++
 cmd/models-schema/zz_generated.openapi.go     |  8 +++++-
 ...re.cluster.x-k8s.io_openstackmachines.yaml | 22 +++++++++++++++
 controllers/openstackmachine_controller.go    |  8 ++++++
 docs/book/src/api/v1beta1/api.md              | 13 +++++++++
 .../api/v1beta1/openstackmachinestatus.go     | 27 ++++++++++++-------
 .../applyconfiguration/internal/internal.go   |  3 +++
 8 files changed, 81 insertions(+), 10 deletions(-)

diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go
index 7d271e78b5..094c439d4b 100644
--- a/api/v1beta1/openstackmachine_types.go
+++ b/api/v1beta1/openstackmachine_types.go
@@ -235,6 +235,11 @@ type OpenStackMachineStatus struct {
 	FailureMessage *string `json:"failureMessage,omitempty"`
 
 	Conditions clusterv1.Conditions `json:"conditions,omitempty"`
+
+	// OpenStackServerRef is a reference to the OpenStackServer object that
+	// is associated with this OpenStackMachine.
+	// +optional
+	OpenStackServerRef *corev1.TypedLocalObjectReference `json:"openStackServerRef,omitempty"`
 }
 
 // +genclient
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index d10b48a05a..27fe7bbff8 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -1117,6 +1117,11 @@ func (in *OpenStackMachineStatus) DeepCopyInto(out *OpenStackMachineStatus) {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
 	}
+	if in.OpenStackServerRef != nil {
+		in, out := &in.OpenStackServerRef, &out.OpenStackServerRef
+		*out = new(v1.TypedLocalObjectReference)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackMachineStatus.
diff --git a/cmd/models-schema/zz_generated.openapi.go b/cmd/models-schema/zz_generated.openapi.go
index 0142d35a62..2303dcbd4e 100644
--- a/cmd/models-schema/zz_generated.openapi.go
+++ b/cmd/models-schema/zz_generated.openapi.go
@@ -19234,11 +19234,17 @@ func schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_OpenStackMachin
 							},
 						},
 					},
+					"openStackServerRef": {
+						SchemaProps: spec.SchemaProps{
+							Description: "OpenStackServerRef is a reference to the OpenStackServer object that is associated with this OpenStackMachine.",
+							Ref:         ref("k8s.io/api/core/v1.TypedLocalObjectReference"),
+						},
+					},
 				},
 			},
 		},
 		Dependencies: []string{
-			"k8s.io/api/core/v1.NodeAddress", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.MachineResources", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ResolvedMachineSpec", "sigs.k8s.io/cluster-api/api/v1beta1.Condition"},
+			"k8s.io/api/core/v1.NodeAddress", "k8s.io/api/core/v1.TypedLocalObjectReference", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.MachineResources", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ResolvedMachineSpec", "sigs.k8s.io/cluster-api/api/v1beta1.Condition"},
 	}
 }
 
diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
index 0e28d57143..19939ad202 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml
@@ -1032,6 +1032,28 @@ spec:
                   This field is not set anymore by the OpenStackMachine controller.
                   Instead, it's set by the OpenStackServer controller.
                 type: string
+              openStackServerRef:
+                description: |-
+                  OpenStackServerRef is a reference to the OpenStackServer object that
+                  is associated with this OpenStackMachine.
+                properties:
+                  apiGroup:
+                    description: |-
+                      APIGroup is the group for the resource being referenced.
+                      If APIGroup is not specified, the specified Kind must be in the core API group.
+                      For any other third-party types, APIGroup is required.
+                    type: string
+                  kind:
+                    description: Kind is the type of resource being referenced
+                    type: string
+                  name:
+                    description: Name is the name of resource being referenced
+                    type: string
+                required:
+                - kind
+                - name
+                type: object
+                x-kubernetes-map-type: atomic
               ready:
                 description: Ready is true when the provider resource is ready.
                 type: boolean
diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go
index 6a7318911a..829e5a8355 100644
--- a/controllers/openstackmachine_controller.go
+++ b/controllers/openstackmachine_controller.go
@@ -365,6 +365,14 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope
 		return ctrl.Result{}, err
 	}
 
+	if machineServer != nil {
+		openStackMachine.Status.OpenStackServerRef = &corev1.TypedLocalObjectReference{
+			APIGroup: &infrav1alpha1.SchemeGroupVersion.Group,
+			Kind:     machineServer.Kind,
+			Name:     machineServer.Name,
+		}
+	}
+
 	computeService, err := compute.NewService(scope)
 	if err != nil {
 		return ctrl.Result{}, err
diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md
index 00e763491e..06b8c2d0c3 100644
--- a/docs/book/src/api/v1beta1/api.md
+++ b/docs/book/src/api/v1beta1/api.md
@@ -3629,6 +3629,19 @@ sigs.k8s.io/cluster-api/api/v1beta1.Conditions
 <td>
 </td>
 </tr>
+<tr>
+<td>
+<code>openStackServerRef</code><br/>
+<em>
+Kubernetes core/v1.TypedLocalObjectReference
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>OpenStackServerRef is a reference to the OpenStackServer object that
+is associated with this OpenStackMachine.</p>
+</td>
+</tr>
 </tbody>
 </table>
 <h3 id="infrastructure.cluster.x-k8s.io/v1beta1.OpenStackMachineTemplateResource">OpenStackMachineTemplateResource
diff --git a/pkg/generated/applyconfiguration/api/v1beta1/openstackmachinestatus.go b/pkg/generated/applyconfiguration/api/v1beta1/openstackmachinestatus.go
index 02184aadf5..92964943d3 100644
--- a/pkg/generated/applyconfiguration/api/v1beta1/openstackmachinestatus.go
+++ b/pkg/generated/applyconfiguration/api/v1beta1/openstackmachinestatus.go
@@ -28,15 +28,16 @@ import (
 // OpenStackMachineStatusApplyConfiguration represents a declarative configuration of the OpenStackMachineStatus type for use
 // with apply.
 type OpenStackMachineStatusApplyConfiguration struct {
-	Ready          *bool                                    `json:"ready,omitempty"`
-	InstanceID     *string                                  `json:"instanceID,omitempty"`
-	Addresses      []v1.NodeAddress                         `json:"addresses,omitempty"`
-	InstanceState  *apiv1beta1.InstanceState                `json:"instanceState,omitempty"`
-	Resolved       *ResolvedMachineSpecApplyConfiguration   `json:"resolved,omitempty"`
-	Resources      *MachineResourcesApplyConfiguration      `json:"resources,omitempty"`
-	FailureReason  *errors.DeprecatedCAPIMachineStatusError `json:"failureReason,omitempty"`
-	FailureMessage *string                                  `json:"failureMessage,omitempty"`
-	Conditions     *clusterapiapiv1beta1.Conditions         `json:"conditions,omitempty"`
+	Ready              *bool                                    `json:"ready,omitempty"`
+	InstanceID         *string                                  `json:"instanceID,omitempty"`
+	Addresses          []v1.NodeAddress                         `json:"addresses,omitempty"`
+	InstanceState      *apiv1beta1.InstanceState                `json:"instanceState,omitempty"`
+	Resolved           *ResolvedMachineSpecApplyConfiguration   `json:"resolved,omitempty"`
+	Resources          *MachineResourcesApplyConfiguration      `json:"resources,omitempty"`
+	FailureReason      *errors.DeprecatedCAPIMachineStatusError `json:"failureReason,omitempty"`
+	FailureMessage     *string                                  `json:"failureMessage,omitempty"`
+	Conditions         *clusterapiapiv1beta1.Conditions         `json:"conditions,omitempty"`
+	OpenStackServerRef *v1.TypedLocalObjectReference            `json:"openStackServerRef,omitempty"`
 }
 
 // OpenStackMachineStatusApplyConfiguration constructs a declarative configuration of the OpenStackMachineStatus type for use with
@@ -118,3 +119,11 @@ func (b *OpenStackMachineStatusApplyConfiguration) WithConditions(value clustera
 	b.Conditions = &value
 	return b
 }
+
+// WithOpenStackServerRef sets the OpenStackServerRef field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the OpenStackServerRef field is set to the value of the last call.
+func (b *OpenStackMachineStatusApplyConfiguration) WithOpenStackServerRef(value v1.TypedLocalObjectReference) *OpenStackMachineStatusApplyConfiguration {
+	b.OpenStackServerRef = &value
+	return b
+}
diff --git a/pkg/generated/applyconfiguration/internal/internal.go b/pkg/generated/applyconfiguration/internal/internal.go
index 46d86085d8..1e3e468059 100644
--- a/pkg/generated/applyconfiguration/internal/internal.go
+++ b/pkg/generated/applyconfiguration/internal/internal.go
@@ -1029,6 +1029,9 @@ var schemaYAML = typed.YAMLObject(`types:
     - name: instanceState
       type:
         scalar: string
+    - name: openStackServerRef
+      type:
+        namedType: io.k8s.api.core.v1.TypedLocalObjectReference
     - name: ready
       type:
         scalar: boolean