@@ -21,9 +21,12 @@ import (
2121
2222 mapiv1beta1 "github.com/openshift/api/machine/v1beta1"
2323
24+ corev1 "k8s.io/api/core/v1"
2425 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2526 "k8s.io/apimachinery/pkg/util/validation/field"
27+ "k8s.io/utils/ptr"
2628 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
29+ capierrors "sigs.k8s.io/cluster-api/errors"
2730)
2831
2932const (
@@ -36,6 +39,11 @@ func fromCAPIMachineToMAPIMachine(capiMachine *clusterv1.Machine) (*mapiv1beta1.
3639
3740 lifecycleHooks , capiMachineNonHookAnnotations := convertCAPILifecycleHookAnnotationsToMAPILifecycleHooksAndAnnotations (capiMachine .Annotations )
3841
42+ mapiMachineStatus , machineStatusErrs := convertCAPIMachineStatusToMAPI (capiMachine .Status )
43+ if len (machineStatusErrs ) > 0 {
44+ errs = append (errs , machineStatusErrs ... )
45+ }
46+
3947 mapiMachine := & mapiv1beta1.Machine {
4048 ObjectMeta : metav1.ObjectMeta {
4149 Name : capiMachine .Name ,
@@ -55,6 +63,7 @@ func fromCAPIMachineToMAPIMachine(capiMachine *clusterv1.Machine) (*mapiv1beta1.
5563 // ProviderSpec: // ProviderSpec MUST NOT be populated here. It is added later by higher level fuctions.
5664 // Taints: // TODO(OCPCLOUD-2861): Taint propagation from Machines to Nodes is not yet implemented in CAPI.
5765 },
66+ Status : mapiMachineStatus ,
5867 }
5968
6069 // Unused fields - Below this line are fields not used from the CAPI Machine.
@@ -99,6 +108,114 @@ func fromCAPIMachineToMAPIMachine(capiMachine *clusterv1.Machine) (*mapiv1beta1.
99108 return mapiMachine , nil
100109}
101110
111+ // convertCAPIMachineStatusToMAPI converts a CAPI MachineStatus to MAPI format.
112+ func convertCAPIMachineStatusToMAPI (capiStatus clusterv1.MachineStatus ) (mapiv1beta1.MachineStatus , field.ErrorList ) {
113+ errs := field.ErrorList {}
114+
115+ addresses , addressesErr := convertCAPIMachineAddressesToMAPI (capiStatus .Addresses )
116+ if addressesErr != nil {
117+ errs = append (errs , addressesErr ... )
118+ }
119+
120+ mapiStatus := mapiv1beta1.MachineStatus {
121+ NodeRef : capiStatus .NodeRef ,
122+ LastUpdated : capiStatus .LastUpdated ,
123+ // Conditions: // TODO(OCPCLOUD-3193): Add MAPI conditions when they are implemented.
124+ ErrorReason : convertCAPIMachineFailureReasonToMAPIErrorReason (capiStatus .FailureReason ),
125+ ErrorMessage : convertCAPIMachineFailureMessageToMAPIErrorMessage (capiStatus .FailureMessage ),
126+ Phase : convertCAPIMachinePhaseToMAPI (capiStatus .Phase ),
127+ Addresses : addresses ,
128+
129+ // LastOperation // this is MAPI-specific and not used in CAPI.
130+ // ObservedGeneration: // We don't set the observed generation at this stage as it is handled by the machineSync controller.
131+ // AuthoritativeAPI: // Ignore, this field as it is not present in CAPI.
132+ // SynchronizedGeneration: // Ignore, this field as it is not present in CAPI.
133+ }
134+
135+ // unused fields from CAPI MachineStatus
136+ // - NodeInfo: not present on the MAPI Machine status.
137+ // - CertificatesExpiryDate: not present on the MAPI Machine status.
138+ // - BootstrapReady: this is derived and not stored directly in MAPI.
139+ // - InfrastructureReady: this is derived and not stored directly in MAPI.
140+ // - Deletion: not present on the MAPI Machine status.
141+ // - V1Beta2: for now we use the V1Beta1 status fields to obtain the status of the MAPI Machine.
142+
143+ return mapiStatus , errs
144+ }
145+
146+ // convertCAPIMachineAddressesToMAPI converts CAPI machine addresses to MAPI format.
147+ func convertCAPIMachineAddressesToMAPI (capiAddresses clusterv1.MachineAddresses ) ([]corev1.NodeAddress , field.ErrorList ) {
148+ if capiAddresses == nil {
149+ return nil , nil
150+ }
151+
152+ errs := field.ErrorList {}
153+ mapiAddresses := make ([]corev1.NodeAddress , 0 , len (capiAddresses ))
154+
155+ // Addresses are slightly different between MAPI/CAPI.
156+ for _ , addr := range capiAddresses {
157+ switch addr .Type {
158+ case clusterv1 .MachineHostName :
159+ mapiAddresses = append (mapiAddresses , corev1.NodeAddress {Type : corev1 .NodeHostName , Address : addr .Address })
160+ case clusterv1 .MachineExternalIP :
161+ mapiAddresses = append (mapiAddresses , corev1.NodeAddress {Type : corev1 .NodeExternalIP , Address : addr .Address })
162+ case clusterv1 .MachineInternalIP :
163+ mapiAddresses = append (mapiAddresses , corev1.NodeAddress {Type : corev1 .NodeInternalIP , Address : addr .Address })
164+ case clusterv1 .MachineExternalDNS :
165+ mapiAddresses = append (mapiAddresses , corev1.NodeAddress {Type : corev1 .NodeExternalDNS , Address : addr .Address })
166+ case clusterv1 .MachineInternalDNS :
167+ mapiAddresses = append (mapiAddresses , corev1.NodeAddress {Type : corev1 .NodeInternalDNS , Address : addr .Address })
168+ default :
169+ errs = append (errs , field .Invalid (field .NewPath ("status" , "addresses" ), string (addr .Type ), string (addr .Type )+ " unrecognized address type" ))
170+ }
171+ }
172+
173+ return mapiAddresses , errs
174+ }
175+
176+ // convertCAPIMachinePhaseToMAPI converts CAPI machine phase to MAPI format.
177+ func convertCAPIMachinePhaseToMAPI (capiPhase string ) * string {
178+ // Phase is slightly different between MAPI/CAPI.
179+ // In CAPI can be one of: Pending;Provisioning;Provisioned;Running;Deleting;Deleted;Failed;Unknown
180+ // In MAPI can be one of: Provisioning;Provisioned;Running;Deleting;Failed (missing Pending,Deleted,Unknown)
181+ switch capiPhase {
182+ case "" :
183+ return nil // Empty is equivalent to nil in MAPI.
184+ case "Pending" :
185+ return nil // Pending is not supported in MAPI but is is a very early state so we don't need to represent it.
186+ case "Deleted" :
187+ return ptr .To ("Deleting" ) // Deleted is not supported in MAPI but we can stay in Deleting until the machine is fully removed.
188+ case "Unknown" :
189+ return nil // Unknown is not supported in MAPI but we can set it to nil until we know more.
190+ case "Provisioning" , "Provisioned" , "Running" , "Deleting" , "Failed" :
191+ return & capiPhase // This is a supported phase so we can represent it in MAPI.
192+ default :
193+ return nil // This is an unknown phase so we can't represent it in MAPI.
194+ }
195+ }
196+
197+ // convertCAPIMachineFailureReasonToMAPIErrorReason converts CAPI MachineStatusError to MAPI MachineStatusError.
198+ func convertCAPIMachineFailureReasonToMAPIErrorReason (capiFailureReason * capierrors.MachineStatusError ) * mapiv1beta1.MachineStatusError {
199+ if capiFailureReason == nil {
200+ return nil
201+ }
202+
203+ mapiErrorReason := mapiv1beta1 .MachineStatusError (* capiFailureReason )
204+
205+ return & mapiErrorReason
206+ }
207+
208+ // convertCAPIMachineFailureMessageToMAPIErrorMessage converts CAPI MachineStatusError to MAPI MachineStatusError.
209+ func convertCAPIMachineFailureMessageToMAPIErrorMessage (capiFailureMessage * string ) * string {
210+ if capiFailureMessage == nil {
211+ return nil
212+ }
213+
214+ mapiErrorMessage := * capiFailureMessage
215+
216+ return & mapiErrorMessage
217+ }
218+
102219const (
103220 // Note the trailing slash here is important when we are trimming the prefix.
104221 capiPreDrainAnnotationPrefix = clusterv1 .PreDrainDeleteHookAnnotationPrefix + "/"
0 commit comments