Skip to content

Commit 47ec67e

Browse files
committed
feat: implement v1beta1 to v1beta2 conversion webhooks
Signed-off-by: Bharath Nallapeta <nr.bharath97@gmail.com>
1 parent 079da9c commit 47ec67e

File tree

6 files changed

+782
-36
lines changed

6 files changed

+782
-36
lines changed

api/v1beta1/conversion.go

Lines changed: 291 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,33 +18,308 @@ package v1beta1
1818

1919
import (
2020
"strings"
21+
"unsafe"
2122

2223
"k8s.io/utils/ptr"
24+
clusterv1beta1 "sigs.k8s.io/cluster-api/api/core/v1beta1"
25+
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2"
26+
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
27+
"sigs.k8s.io/controller-runtime/pkg/conversion"
28+
29+
infrav1beta2 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta2"
2330
)
2431

25-
// Hub marks OpenStackCluster as a conversion hub.
26-
func (*OpenStackCluster) Hub() {}
32+
// ConvertTo converts this OpenStackCluster to the Hub version (v1beta2).
33+
func (src *OpenStackCluster) ConvertTo(dstRaw conversion.Hub) error {
34+
dst := dstRaw.(*infrav1beta2.OpenStackCluster)
35+
36+
// Copy metadata
37+
dst.ObjectMeta = src.ObjectMeta
38+
39+
// Copy Spec (using unsafe pointer since struct layouts are identical)
40+
dst.Spec = *(*infrav1beta2.OpenStackClusterSpec)(unsafe.Pointer(&src.Spec))
41+
42+
// Convert Status - most fields are identical structures
43+
dst.Status.Initialization = (*infrav1beta2.ClusterInitialization)(unsafe.Pointer(src.Status.Initialization))
44+
dst.Status.Network = (*infrav1beta2.NetworkStatusWithSubnets)(unsafe.Pointer(src.Status.Network))
45+
dst.Status.ExternalNetwork = (*infrav1beta2.NetworkStatus)(unsafe.Pointer(src.Status.ExternalNetwork))
46+
dst.Status.Router = (*infrav1beta2.Router)(unsafe.Pointer(src.Status.Router))
47+
dst.Status.APIServerLoadBalancer = (*infrav1beta2.LoadBalancer)(unsafe.Pointer(src.Status.APIServerLoadBalancer))
48+
dst.Status.ControlPlaneSecurityGroup = (*infrav1beta2.SecurityGroupStatus)(unsafe.Pointer(src.Status.ControlPlaneSecurityGroup))
49+
dst.Status.WorkerSecurityGroup = (*infrav1beta2.SecurityGroupStatus)(unsafe.Pointer(src.Status.WorkerSecurityGroup))
50+
dst.Status.BastionSecurityGroup = (*infrav1beta2.SecurityGroupStatus)(unsafe.Pointer(src.Status.BastionSecurityGroup))
51+
dst.Status.Bastion = (*infrav1beta2.BastionStatus)(unsafe.Pointer(src.Status.Bastion))
52+
53+
// Convert FailureDomains from map to slice
54+
// v1beta1: map[string]FailureDomainSpec where FailureDomainSpec has ControlPlane bool (not pointer)
55+
// v1beta2: []FailureDomain where FailureDomain has ControlPlane *bool and Name string
56+
if len(src.Status.FailureDomains) > 0 {
57+
dst.Status.FailureDomains = make([]clusterv1.FailureDomain, 0, len(src.Status.FailureDomains))
58+
for name, fd := range src.Status.FailureDomains {
59+
dst.Status.FailureDomains = append(dst.Status.FailureDomains, clusterv1.FailureDomain{
60+
Name: name,
61+
ControlPlane: ptr.To(fd.ControlPlane),
62+
Attributes: fd.Attributes,
63+
})
64+
}
65+
}
66+
67+
// Convert conditions (v1beta1 format -> standard k8s format)
68+
dst.Status.Conditions = infrav1beta2.ConvertConditionsToV1Beta2(src.Status.Conditions, src.Generation)
69+
70+
// Store original object for restoration
71+
return utilconversion.MarshalData(src, dst)
72+
}
73+
74+
// ConvertFrom converts from the Hub version (v1beta2) to this version.
75+
//
76+
//nolint:revive // dst is the receiver here (converting FROM hub TO spoke)
77+
func (dst *OpenStackCluster) ConvertFrom(srcRaw conversion.Hub) error {
78+
src := srcRaw.(*infrav1beta2.OpenStackCluster)
79+
80+
// Copy metadata
81+
dst.ObjectMeta = src.ObjectMeta
82+
83+
// Copy Spec (using unsafe pointer since struct layouts are identical)
84+
dst.Spec = *(*OpenStackClusterSpec)(unsafe.Pointer(&src.Spec))
85+
86+
// Convert Status
87+
dst.Status.Initialization = (*ClusterInitialization)(unsafe.Pointer(src.Status.Initialization))
88+
dst.Status.Network = (*NetworkStatusWithSubnets)(unsafe.Pointer(src.Status.Network))
89+
dst.Status.ExternalNetwork = (*NetworkStatus)(unsafe.Pointer(src.Status.ExternalNetwork))
90+
dst.Status.Router = (*Router)(unsafe.Pointer(src.Status.Router))
91+
dst.Status.APIServerLoadBalancer = (*LoadBalancer)(unsafe.Pointer(src.Status.APIServerLoadBalancer))
92+
dst.Status.ControlPlaneSecurityGroup = (*SecurityGroupStatus)(unsafe.Pointer(src.Status.ControlPlaneSecurityGroup))
93+
dst.Status.WorkerSecurityGroup = (*SecurityGroupStatus)(unsafe.Pointer(src.Status.WorkerSecurityGroup))
94+
dst.Status.BastionSecurityGroup = (*SecurityGroupStatus)(unsafe.Pointer(src.Status.BastionSecurityGroup))
95+
dst.Status.Bastion = (*BastionStatus)(unsafe.Pointer(src.Status.Bastion))
96+
97+
// Convert FailureDomains from slice to map
98+
// v1beta2: []FailureDomain where FailureDomain has ControlPlane *bool and Name string
99+
// v1beta1: map[string]FailureDomainSpec where FailureDomainSpec has ControlPlane bool (not pointer)
100+
if len(src.Status.FailureDomains) > 0 {
101+
dst.Status.FailureDomains = make(clusterv1beta1.FailureDomains, len(src.Status.FailureDomains))
102+
for _, fd := range src.Status.FailureDomains {
103+
controlPlane := false
104+
if fd.ControlPlane != nil {
105+
controlPlane = *fd.ControlPlane
106+
}
107+
dst.Status.FailureDomains[fd.Name] = clusterv1beta1.FailureDomainSpec{
108+
ControlPlane: controlPlane,
109+
Attributes: fd.Attributes,
110+
}
111+
}
112+
}
113+
114+
// Convert conditions (standard k8s format -> v1beta1 format)
115+
dst.Status.Conditions = infrav1beta2.ConvertConditionsFromV1Beta2(src.Status.Conditions)
116+
117+
// Derive deprecated Ready field from Ready condition
118+
dst.Status.Ready = infrav1beta2.IsReady(src.Status.Conditions)
119+
// FailureReason and FailureMessage stay nil (deprecated)
120+
121+
// Restore original data
122+
_, err := utilconversion.UnmarshalData(src, dst)
123+
return err
124+
}
125+
126+
// ConvertTo converts this OpenStackMachine to the Hub version (v1beta2).
127+
func (src *OpenStackMachine) ConvertTo(dstRaw conversion.Hub) error {
128+
dst := dstRaw.(*infrav1beta2.OpenStackMachine)
27129

28-
// Hub marks OpenStackClusterList as a conversion hub.
29-
func (*OpenStackClusterList) Hub() {}
130+
// Copy metadata and spec
131+
dst.ObjectMeta = src.ObjectMeta
132+
dst.Spec = *(*infrav1beta2.OpenStackMachineSpec)(unsafe.Pointer(&src.Spec))
133+
134+
// Convert status
135+
dst.Status.Initialization = (*infrav1beta2.MachineInitialization)(unsafe.Pointer(src.Status.Initialization))
136+
dst.Status.InstanceID = src.Status.InstanceID
137+
dst.Status.InstanceState = (*infrav1beta2.InstanceState)(unsafe.Pointer(src.Status.InstanceState))
138+
dst.Status.Resolved = (*infrav1beta2.ResolvedMachineSpec)(unsafe.Pointer(src.Status.Resolved))
139+
dst.Status.Resources = (*infrav1beta2.MachineResources)(unsafe.Pointer(src.Status.Resources))
140+
dst.Status.Addresses = src.Status.Addresses
141+
142+
// Convert conditions
143+
dst.Status.Conditions = infrav1beta2.ConvertConditionsToV1Beta2(src.Status.Conditions, src.Generation)
144+
145+
return utilconversion.MarshalData(src, dst)
146+
}
30147

31-
// Hub marks OpenStackClusterTemplate as a conversion hub.
32-
func (*OpenStackClusterTemplate) Hub() {}
148+
// ConvertFrom converts from the Hub version (v1beta2) to this version.
149+
//
150+
//nolint:revive // dst is the receiver here (converting FROM hub TO spoke)
151+
func (dst *OpenStackMachine) ConvertFrom(srcRaw conversion.Hub) error {
152+
src := srcRaw.(*infrav1beta2.OpenStackMachine)
33153

34-
// Hub marks OpenStackClusterTemplateList as a conversion hub.
35-
func (*OpenStackClusterTemplateList) Hub() {}
154+
// Copy metadata and spec
155+
dst.ObjectMeta = src.ObjectMeta
156+
dst.Spec = *(*OpenStackMachineSpec)(unsafe.Pointer(&src.Spec))
36157

37-
// Hub marks OpenStackMachine as a conversion hub.
38-
func (*OpenStackMachine) Hub() {}
158+
// Convert status
159+
dst.Status.Initialization = (*MachineInitialization)(unsafe.Pointer(src.Status.Initialization))
160+
dst.Status.InstanceID = src.Status.InstanceID
161+
dst.Status.InstanceState = (*InstanceState)(unsafe.Pointer(src.Status.InstanceState))
162+
dst.Status.Resolved = (*ResolvedMachineSpec)(unsafe.Pointer(src.Status.Resolved))
163+
dst.Status.Resources = (*MachineResources)(unsafe.Pointer(src.Status.Resources))
164+
dst.Status.Addresses = src.Status.Addresses
39165

40-
// Hub marks OpenStackMachineList as a conversion hub.
41-
func (*OpenStackMachineList) Hub() {}
166+
// Convert conditions
167+
dst.Status.Conditions = infrav1beta2.ConvertConditionsFromV1Beta2(src.Status.Conditions)
42168

43-
// Hub marks OpenStackMachineTemplate as a conversion hub.
44-
func (*OpenStackMachineTemplate) Hub() {}
169+
// Derive deprecated fields
170+
dst.Status.Ready = infrav1beta2.IsReady(src.Status.Conditions)
171+
172+
_, err := utilconversion.UnmarshalData(src, dst)
173+
return err
174+
}
175+
176+
// ConvertTo converts this OpenStackClusterTemplate to the Hub version (v1beta2).
177+
func (src *OpenStackClusterTemplate) ConvertTo(dstRaw conversion.Hub) error {
178+
dst := dstRaw.(*infrav1beta2.OpenStackClusterTemplate)
179+
dst.ObjectMeta = src.ObjectMeta
180+
dst.Spec.Template.Spec = *(*infrav1beta2.OpenStackClusterSpec)(unsafe.Pointer(&src.Spec.Template.Spec))
181+
return nil
182+
}
183+
184+
// ConvertFrom converts from the Hub version (v1beta2) to this version.
185+
//
186+
//nolint:revive // dst is the receiver here (converting FROM hub TO spoke)
187+
func (dst *OpenStackClusterTemplate) ConvertFrom(srcRaw conversion.Hub) error {
188+
src := srcRaw.(*infrav1beta2.OpenStackClusterTemplate)
189+
dst.ObjectMeta = src.ObjectMeta
190+
dst.Spec.Template.Spec = *(*OpenStackClusterSpec)(unsafe.Pointer(&src.Spec.Template.Spec))
191+
return nil
192+
}
193+
194+
// ConvertTo converts this OpenStackMachineTemplate to the Hub version (v1beta2).
195+
func (src *OpenStackMachineTemplate) ConvertTo(dstRaw conversion.Hub) error {
196+
dst := dstRaw.(*infrav1beta2.OpenStackMachineTemplate)
197+
dst.ObjectMeta = src.ObjectMeta
198+
dst.Spec.Template.Spec = *(*infrav1beta2.OpenStackMachineSpec)(unsafe.Pointer(&src.Spec.Template.Spec))
199+
return nil
200+
}
45201

46-
// Hub marks OpenStackMachineTemplateList as a conversion hub.
47-
func (*OpenStackMachineTemplateList) Hub() {}
202+
// ConvertFrom converts from the Hub version (v1beta2) to this version.
203+
//
204+
//nolint:revive // dst is the receiver here (converting FROM hub TO spoke)
205+
func (dst *OpenStackMachineTemplate) ConvertFrom(srcRaw conversion.Hub) error {
206+
src := srcRaw.(*infrav1beta2.OpenStackMachineTemplate)
207+
dst.ObjectMeta = src.ObjectMeta
208+
dst.Spec.Template.Spec = *(*OpenStackMachineSpec)(unsafe.Pointer(&src.Spec.Template.Spec))
209+
return nil
210+
}
211+
212+
// ConvertTo converts this OpenStackClusterList to the Hub version (v1beta2).
213+
func (src *OpenStackClusterList) ConvertTo(dstRaw conversion.Hub) error {
214+
dst := dstRaw.(*infrav1beta2.OpenStackClusterList)
215+
dst.ListMeta = src.ListMeta
216+
dst.Items = make([]infrav1beta2.OpenStackCluster, len(src.Items))
217+
for i := range src.Items {
218+
if err := src.Items[i].ConvertTo(&dst.Items[i]); err != nil {
219+
return err
220+
}
221+
}
222+
return nil
223+
}
224+
225+
// ConvertFrom converts from the Hub version (v1beta2) to this version.
226+
//
227+
//nolint:revive // dst is the receiver here (converting FROM hub TO spoke)
228+
func (dst *OpenStackClusterList) ConvertFrom(srcRaw conversion.Hub) error {
229+
src := srcRaw.(*infrav1beta2.OpenStackClusterList)
230+
dst.ListMeta = src.ListMeta
231+
dst.Items = make([]OpenStackCluster, len(src.Items))
232+
for i := range src.Items {
233+
if err := dst.Items[i].ConvertFrom(&src.Items[i]); err != nil {
234+
return err
235+
}
236+
}
237+
return nil
238+
}
239+
240+
// ConvertTo converts this OpenStackMachineList to the Hub version (v1beta2).
241+
func (src *OpenStackMachineList) ConvertTo(dstRaw conversion.Hub) error {
242+
dst := dstRaw.(*infrav1beta2.OpenStackMachineList)
243+
dst.ListMeta = src.ListMeta
244+
dst.Items = make([]infrav1beta2.OpenStackMachine, len(src.Items))
245+
for i := range src.Items {
246+
if err := src.Items[i].ConvertTo(&dst.Items[i]); err != nil {
247+
return err
248+
}
249+
}
250+
return nil
251+
}
252+
253+
// ConvertFrom converts from the Hub version (v1beta2) to this version.
254+
//
255+
//nolint:revive // dst is the receiver here (converting FROM hub TO spoke)
256+
func (dst *OpenStackMachineList) ConvertFrom(srcRaw conversion.Hub) error {
257+
src := srcRaw.(*infrav1beta2.OpenStackMachineList)
258+
dst.ListMeta = src.ListMeta
259+
dst.Items = make([]OpenStackMachine, len(src.Items))
260+
for i := range src.Items {
261+
if err := dst.Items[i].ConvertFrom(&src.Items[i]); err != nil {
262+
return err
263+
}
264+
}
265+
return nil
266+
}
267+
268+
// ConvertTo converts this OpenStackClusterTemplateList to the Hub version (v1beta2).
269+
func (src *OpenStackClusterTemplateList) ConvertTo(dstRaw conversion.Hub) error {
270+
dst := dstRaw.(*infrav1beta2.OpenStackClusterTemplateList)
271+
dst.ListMeta = src.ListMeta
272+
dst.Items = make([]infrav1beta2.OpenStackClusterTemplate, len(src.Items))
273+
for i := range src.Items {
274+
if err := src.Items[i].ConvertTo(&dst.Items[i]); err != nil {
275+
return err
276+
}
277+
}
278+
return nil
279+
}
280+
281+
// ConvertFrom converts from the Hub version (v1beta2) to this version.
282+
//
283+
//nolint:revive // dst is the receiver here (converting FROM hub TO spoke)
284+
func (dst *OpenStackClusterTemplateList) ConvertFrom(srcRaw conversion.Hub) error {
285+
src := srcRaw.(*infrav1beta2.OpenStackClusterTemplateList)
286+
dst.ListMeta = src.ListMeta
287+
dst.Items = make([]OpenStackClusterTemplate, len(src.Items))
288+
for i := range src.Items {
289+
if err := dst.Items[i].ConvertFrom(&src.Items[i]); err != nil {
290+
return err
291+
}
292+
}
293+
return nil
294+
}
295+
296+
// ConvertTo converts this OpenStackMachineTemplateList to the Hub version (v1beta2).
297+
func (src *OpenStackMachineTemplateList) ConvertTo(dstRaw conversion.Hub) error {
298+
dst := dstRaw.(*infrav1beta2.OpenStackMachineTemplateList)
299+
dst.ListMeta = src.ListMeta
300+
dst.Items = make([]infrav1beta2.OpenStackMachineTemplate, len(src.Items))
301+
for i := range src.Items {
302+
if err := src.Items[i].ConvertTo(&dst.Items[i]); err != nil {
303+
return err
304+
}
305+
}
306+
return nil
307+
}
308+
309+
// ConvertFrom converts from the Hub version (v1beta2) to this version.
310+
//
311+
//nolint:revive // dst is the receiver here (converting FROM hub TO spoke)
312+
func (dst *OpenStackMachineTemplateList) ConvertFrom(srcRaw conversion.Hub) error {
313+
src := srcRaw.(*infrav1beta2.OpenStackMachineTemplateList)
314+
dst.ListMeta = src.ListMeta
315+
dst.Items = make([]OpenStackMachineTemplate, len(src.Items))
316+
for i := range src.Items {
317+
if err := dst.Items[i].ConvertFrom(&src.Items[i]); err != nil {
318+
return err
319+
}
320+
}
321+
return nil
322+
}
48323

49324
// LegacyCalicoSecurityGroupRules returns a list of security group rules for calico
50325
// that need to be applied to the control plane and worker security groups when

0 commit comments

Comments
 (0)