Skip to content

Commit efb3f2e

Browse files
committed
fix deprecated client.Apply with applyconfig types
Signed-off-by: Rohit Kumar <rohit.1si09ee045@gmail.com>
1 parent 9968c7a commit efb3f2e

2 files changed

Lines changed: 183 additions & 111 deletions

File tree

pkg/cloudprovider/ironcore/load_balancer.go

Lines changed: 182 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ import (
1717
servicehelper "k8s.io/cloud-provider/service/helpers"
1818
"k8s.io/klog/v2"
1919

20+
ipamv1alpha1ac "github.com/ironcore-dev/ironcore/client-go/applyconfigurations/ipam/v1alpha1"
21+
networkingv1alpha1ac "github.com/ironcore-dev/ironcore/client-go/applyconfigurations/networking/v1alpha1"
2022
"sigs.k8s.io/controller-runtime/pkg/client"
21-
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
2223

23-
commonv1alpha1 "github.com/ironcore-dev/ironcore/api/common/v1alpha1"
24+
metav1ac "k8s.io/client-go/applyconfigurations/meta/v1"
25+
26+
"github.com/ironcore-dev/ironcore/api/common/v1alpha1"
2427
computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1"
25-
ipamv1alpha1 "github.com/ironcore-dev/ironcore/api/ipam/v1alpha1"
2628
networkingv1alpha1 "github.com/ironcore-dev/ironcore/api/networking/v1alpha1"
2729
)
2830

@@ -104,110 +106,54 @@ func (o *ironcoreLoadBalancer) GetLoadBalancerName(ctx context.Context, clusterN
104106
func (o *ironcoreLoadBalancer) EnsureLoadBalancer(ctx context.Context, clusterName string, service *v1.Service, nodes []*v1.Node) (*v1.LoadBalancerStatus, error) {
105107
klog.V(2).InfoS("EnsureLoadBalancer for Service", "Cluster", clusterName, "Service", client.ObjectKeyFromObject(service))
106108

107-
// decide load balancer type based on service annotation for internal load balancer
108-
var desiredLoadBalancerType networkingv1alpha1.LoadBalancerType
109-
if value, ok := service.Annotations[InternalLoadBalancerAnnotation]; ok && value == "true" {
110-
desiredLoadBalancerType = networkingv1alpha1.LoadBalancerTypeInternal
111-
} else {
112-
desiredLoadBalancerType = networkingv1alpha1.LoadBalancerTypePublic
113-
}
109+
desiredLoadBalancerType := o.getDesiredLoadBalancerType(service)
114110

115111
loadBalancerName, err := o.getLoadBalancerName(ctx, clusterName, service)
116112
if err != nil {
117113
return nil, fmt.Errorf("failed to get LoadBalancer name for Service %s: %w", client.ObjectKeyFromObject(service), err)
118114
}
119115

120-
// get existing load balancer type
121-
existingLoadBalancer := &networkingv1alpha1.LoadBalancer{}
122-
var existingLoadBalancerType networkingv1alpha1.LoadBalancerType
123-
if err := o.ironcoreClient.Get(ctx, client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName}, existingLoadBalancer); err == nil {
124-
existingLoadBalancerType = existingLoadBalancer.Spec.Type
125-
if existingLoadBalancerType != desiredLoadBalancerType {
126-
if err = o.EnsureLoadBalancerDeleted(ctx, clusterName, service); err != nil {
127-
return nil, fmt.Errorf("failed deleting existing loadbalancer %s: %w", loadBalancerName, err)
128-
}
129-
}
116+
existingLoadBalancerType, err := o.ensureLoadBalancerType(ctx, clusterName, service, loadBalancerName, desiredLoadBalancerType)
117+
if err != nil {
118+
return nil, err
130119
}
131120

132-
klog.V(2).InfoS("Getting LoadBalancer ports from Service", "Service", client.ObjectKeyFromObject(service))
133-
var lbPorts []networkingv1alpha1.LoadBalancerPort
134-
for _, svcPort := range service.Spec.Ports {
135-
protocol := svcPort.Protocol
136-
lbPorts = append(lbPorts, networkingv1alpha1.LoadBalancerPort{
137-
Protocol: &protocol,
138-
Port: svcPort.Port,
139-
})
121+
loadBalancerApplyConfig, err := o.buildLoadBalancerApplyConfig(clusterName, service, loadBalancerName, desiredLoadBalancerType)
122+
if err != nil {
123+
return nil, err
140124
}
141125

142-
loadBalancer := &networkingv1alpha1.LoadBalancer{
143-
TypeMeta: metav1.TypeMeta{
144-
Kind: "LoadBalancer",
145-
APIVersion: networkingv1alpha1.SchemeGroupVersion.String(),
146-
},
147-
ObjectMeta: metav1.ObjectMeta{
148-
Name: loadBalancerName,
149-
Namespace: o.ironcoreNamespace,
150-
Annotations: map[string]string{
151-
AnnotationKeyClusterName: clusterName,
152-
AnnotationKeyServiceName: service.Name,
153-
AnnotationKeyServiceNamespace: service.Namespace,
154-
AnnotationKeyServiceUID: string(service.UID),
155-
},
156-
},
157-
Spec: networkingv1alpha1.LoadBalancerSpec{
158-
Type: desiredLoadBalancerType,
159-
IPFamilies: service.Spec.IPFamilies,
160-
NetworkRef: v1.LocalObjectReference{
161-
Name: o.cloudConfig.NetworkName,
162-
},
163-
Ports: lbPorts,
164-
},
165-
}
126+
klog.V(2).InfoS("Applying LoadBalancer for Service", "LoadBalancer", client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName}, "Service", client.ObjectKeyFromObject(service))
166127

167-
// if load balancer type is Internal then update IPSource with valid prefix template
168-
if desiredLoadBalancerType == networkingv1alpha1.LoadBalancerTypeInternal {
169-
if o.cloudConfig.PrefixName == "" {
170-
return nil, fmt.Errorf("prefixName is not defined in config")
171-
}
172-
loadBalancer.Spec.IPs = []networkingv1alpha1.IPSource{
173-
{
174-
Ephemeral: &networkingv1alpha1.EphemeralPrefixSource{
175-
PrefixTemplate: &ipamv1alpha1.PrefixTemplateSpec{
176-
Spec: ipamv1alpha1.PrefixSpec{
177-
// TODO: for now we only support IPv4 until Gardener has support for IPv6 based Shoots
178-
IPFamily: v1.IPv4Protocol,
179-
ParentRef: &v1.LocalObjectReference{
180-
Name: o.cloudConfig.PrefixName,
181-
},
182-
},
183-
},
184-
},
185-
},
186-
}
187-
}
188-
// If useNicSelector is set to true then add NetworkInterfaceSelector to loadbalancer.SPec
189-
if o.useNicSelector {
190-
loadBalancer.Spec.NetworkInterfaceSelector = &metav1.LabelSelector{
191-
MatchLabels: map[string]string{
192-
LabelKeyClusterName: clusterName,
193-
},
194-
}
128+
if err := o.ironcoreClient.Apply(ctx, loadBalancerApplyConfig, client.FieldOwner(loadBalancerFieldOwner), client.ForceOwnership); err != nil {
129+
return nil, fmt.Errorf("failed to apply LoadBalancer %s for Service %s: %w", client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName}, client.ObjectKeyFromObject(service), err)
195130
}
196131

197-
klog.V(2).InfoS("Applying LoadBalancer for Service", "LoadBalancer", client.ObjectKeyFromObject(loadBalancer), "Service", client.ObjectKeyFromObject(service))
198-
if err := o.ironcoreClient.Patch(ctx, loadBalancer, client.Apply, loadBalancerFieldOwner, client.ForceOwnership); err != nil {
199-
return nil, fmt.Errorf("failed to apply LoadBalancer %s for Service %s: %w", client.ObjectKeyFromObject(loadBalancer), client.ObjectKeyFromObject(service), err)
200-
}
201-
klog.V(2).InfoS("Applied LoadBalancer for Service", "LoadBalancer", client.ObjectKeyFromObject(loadBalancer), "Service", client.ObjectKeyFromObject(service))
132+
klog.V(2).InfoS("Applied LoadBalancer for Service", "LoadBalancer", client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName}, "Service", client.ObjectKeyFromObject(service))
202133

203134
// if useNicSelector is set to false then cloudProvider has to create the loadbalancerRouting
204135
// if useNicSelector is set to true then Ironcore will take care of creating the loadbalancerRouting
205136
if !o.useNicSelector {
206-
klog.V(2).InfoS("Applying LoadBalancerRouting for LoadBalancer", "LoadBalancer", client.ObjectKeyFromObject(loadBalancer))
207-
if err := o.applyLoadBalancerRoutingForLoadBalancer(ctx, loadBalancer, nodes); err != nil {
137+
loadBalancerToRoute := &networkingv1alpha1.LoadBalancer{}
138+
loadBalancerKey := client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName}
139+
if err := o.ironcoreClient.Get(ctx, loadBalancerKey, loadBalancerToRoute); err != nil {
140+
return nil, fmt.Errorf("failed to get LoadBalancer %s for routing: %w", loadBalancerKey, err)
141+
}
142+
143+
klog.V(2).InfoS("Applying LoadBalancerRouting for LoadBalancer", "LoadBalancer", client.ObjectKeyFromObject(loadBalancerToRoute))
144+
145+
if err := o.applyLoadBalancerRoutingForLoadBalancer(ctx, loadBalancerToRoute, nodes); err != nil {
208146
return nil, err
209147
}
210-
klog.V(2).InfoS("Applied LoadBalancerRouting for LoadBalancer", "LoadBalancer", client.ObjectKeyFromObject(loadBalancer))
148+
149+
klog.V(2).InfoS("Applied LoadBalancerRouting for LoadBalancer", "LoadBalancer", client.ObjectKeyFromObject(loadBalancerToRoute))
150+
}
151+
152+
loadBalancer := &networkingv1alpha1.LoadBalancer{
153+
ObjectMeta: metav1.ObjectMeta{
154+
Name: loadBalancerName,
155+
Namespace: o.ironcoreNamespace,
156+
},
211157
}
212158

213159
lbStatus, err := waitLoadBalancerActive(ctx, o.ironcoreClient, existingLoadBalancerType, service, loadBalancer)
@@ -217,6 +163,103 @@ func (o *ironcoreLoadBalancer) EnsureLoadBalancer(ctx context.Context, clusterNa
217163
return &lbStatus, nil
218164
}
219165

166+
func (o *ironcoreLoadBalancer) getDesiredLoadBalancerType(service *v1.Service) networkingv1alpha1.LoadBalancerType {
167+
if value, ok := service.Annotations[InternalLoadBalancerAnnotation]; ok && value == "true" {
168+
return networkingv1alpha1.LoadBalancerTypeInternal
169+
}
170+
171+
return networkingv1alpha1.LoadBalancerTypePublic
172+
}
173+
174+
func (o *ironcoreLoadBalancer) ensureLoadBalancerType(ctx context.Context, clusterName string, service *v1.Service, loadBalancerName string,
175+
desiredType networkingv1alpha1.LoadBalancerType,
176+
) (networkingv1alpha1.LoadBalancerType, error) {
177+
existingLoadBalancer := &networkingv1alpha1.LoadBalancer{}
178+
179+
if err := o.ironcoreClient.Get(ctx, client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancerName}, existingLoadBalancer); err != nil {
180+
if apierrors.IsNotFound(err) {
181+
return "", nil
182+
}
183+
184+
return "", err
185+
}
186+
187+
existingType := existingLoadBalancer.Spec.Type
188+
189+
if existingType != desiredType {
190+
if err := o.EnsureLoadBalancerDeleted(ctx, clusterName, service); err != nil {
191+
return "", fmt.Errorf("failed deleting existing loadbalancer %s: %w", loadBalancerName, err)
192+
}
193+
}
194+
195+
return existingType, nil
196+
}
197+
198+
func (o *ironcoreLoadBalancer) buildLoadBalancerApplyConfig(clusterName string, service *v1.Service, loadBalancerName string,
199+
loadBalancerType networkingv1alpha1.LoadBalancerType,
200+
) (*networkingv1alpha1ac.LoadBalancerApplyConfiguration, error) {
201+
lbPorts := make([]*networkingv1alpha1ac.LoadBalancerPortApplyConfiguration, 0, len(service.Spec.Ports))
202+
203+
for _, svcPort := range service.Spec.Ports {
204+
protocol := svcPort.Protocol
205+
206+
lbPorts = append(lbPorts, networkingv1alpha1ac.LoadBalancerPort().
207+
WithProtocol(protocol).
208+
WithPort(svcPort.Port),
209+
)
210+
}
211+
212+
spec := networkingv1alpha1ac.LoadBalancerSpec().
213+
WithType(loadBalancerType).
214+
WithIPFamilies(service.Spec.IPFamilies...).
215+
WithNetworkRef(v1.LocalObjectReference{Name: o.cloudConfig.NetworkName}).
216+
WithPorts(lbPorts...)
217+
218+
if loadBalancerType == networkingv1alpha1.LoadBalancerTypeInternal {
219+
if o.cloudConfig.PrefixName == "" {
220+
return nil, fmt.Errorf("prefixName is not defined in config")
221+
}
222+
223+
spec.WithIPs(
224+
networkingv1alpha1ac.IPSource().
225+
WithEphemeral(
226+
networkingv1alpha1ac.EphemeralPrefixSource().
227+
WithPrefixTemplate(
228+
ipamv1alpha1ac.PrefixTemplateSpec().
229+
WithSpec(
230+
ipamv1alpha1ac.PrefixSpec().
231+
WithIPFamily(v1.IPv4Protocol).
232+
WithParentRef(
233+
v1.LocalObjectReference{
234+
Name: o.cloudConfig.PrefixName,
235+
}),
236+
),
237+
),
238+
),
239+
)
240+
}
241+
242+
if o.useNicSelector {
243+
spec.WithNetworkInterfaceSelector(
244+
metav1ac.LabelSelector().
245+
WithMatchLabels(map[string]string{
246+
LabelKeyClusterName: clusterName,
247+
}),
248+
)
249+
}
250+
251+
return networkingv1alpha1ac.LoadBalancer(
252+
loadBalancerName,
253+
o.ironcoreNamespace,
254+
).
255+
WithAnnotations(map[string]string{
256+
AnnotationKeyClusterName: clusterName,
257+
AnnotationKeyServiceName: service.Name,
258+
AnnotationKeyServiceNamespace: service.Namespace,
259+
AnnotationKeyServiceUID: string(service.UID),
260+
}).
261+
WithSpec(spec), nil
262+
}
220263
func waitLoadBalancerActive(ctx context.Context, ironcoreClient client.Client, existingLoadBalancerType networkingv1alpha1.LoadBalancerType,
221264
service *v1.Service, loadBalancer *networkingv1alpha1.LoadBalancer) (v1.LoadBalancerStatus, error) {
222265
klog.V(2).InfoS("Waiting for LoadBalancer instance to become ready", "LoadBalancer", client.ObjectKeyFromObject(loadBalancer))
@@ -253,43 +296,72 @@ func waitLoadBalancerActive(ctx context.Context, ironcoreClient client.Client, e
253296
}
254297

255298
func (o *ironcoreLoadBalancer) applyLoadBalancerRoutingForLoadBalancer(ctx context.Context, loadBalancer *networkingv1alpha1.LoadBalancer, nodes []*v1.Node) error {
256-
loadBalacerDestinations, err := o.getLoadBalancerDestinationsForNodes(ctx, nodes, loadBalancer.Spec.NetworkRef.Name)
299+
loadBalancerDestinations, err := o.getLoadBalancerDestinationsForNodes(ctx, nodes, loadBalancer.Spec.NetworkRef.Name)
257300
if err != nil {
258301
return fmt.Errorf("failed to get NetworkInterfaces for Nodes: %w", err)
259302
}
260303

261304
network := &networkingv1alpha1.Network{}
262-
networkKey := client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancer.Spec.NetworkRef.Name}
305+
networkKey := client.ObjectKey{
306+
Namespace: o.ironcoreNamespace,
307+
Name: loadBalancer.Spec.NetworkRef.Name,
308+
}
309+
263310
if err := o.ironcoreClient.Get(ctx, networkKey, network); err != nil {
264311
return fmt.Errorf("failed to get Network %s: %w", o.cloudConfig.NetworkName, err)
265312
}
266313

267-
loadBalancerRouting := &networkingv1alpha1.LoadBalancerRouting{
268-
TypeMeta: metav1.TypeMeta{
269-
Kind: "LoadBalancerRouting",
270-
APIVersion: networkingv1alpha1.SchemeGroupVersion.String(),
271-
},
272-
ObjectMeta: metav1.ObjectMeta{
273-
Name: loadBalancer.Name,
274-
Namespace: o.ironcoreNamespace,
275-
},
276-
NetworkRef: commonv1alpha1.LocalUIDReference{
277-
Name: network.Name,
278-
UID: network.UID,
279-
},
280-
Destinations: loadBalacerDestinations,
281-
}
314+
loadBalancerRoutingApplyConfig := o.buildLoadBalancerRoutingApplyConfig(loadBalancer, network, loadBalancerDestinations)
282315

283-
if err := controllerutil.SetOwnerReference(loadBalancer, loadBalancerRouting, o.ironcoreClient.Scheme()); err != nil {
284-
return fmt.Errorf("failed to set owner reference for load balancer routing %s: %w", client.ObjectKeyFromObject(loadBalancerRouting), err)
316+
if err := o.ironcoreClient.Apply(ctx, loadBalancerRoutingApplyConfig, client.FieldOwner(loadBalancerFieldOwner), client.ForceOwnership); err != nil {
317+
return fmt.Errorf("failed to apply LoadBalancerRouting %s for LoadBalancer %s: %w", client.ObjectKey{Namespace: o.ironcoreNamespace, Name: loadBalancer.Name}, client.ObjectKeyFromObject(loadBalancer), err)
285318
}
286319

287-
if err := o.ironcoreClient.Patch(ctx, loadBalancerRouting, client.Apply, loadBalancerFieldOwner, client.ForceOwnership); err != nil {
288-
return fmt.Errorf("failed to apply LoadBalancerRouting %s for LoadBalancer %s: %w", client.ObjectKeyFromObject(loadBalancerRouting), client.ObjectKeyFromObject(loadBalancer), err)
289-
}
290320
return nil
291321
}
292322

323+
func (o *ironcoreLoadBalancer) buildLoadBalancerRoutingApplyConfig(
324+
loadBalancer *networkingv1alpha1.LoadBalancer,
325+
network *networkingv1alpha1.Network,
326+
destinations []networkingv1alpha1.LoadBalancerDestination,
327+
) *networkingv1alpha1ac.LoadBalancerRoutingApplyConfiguration {
328+
destinationApplyConfigs := make([]*networkingv1alpha1ac.LoadBalancerDestinationApplyConfiguration, 0, len(destinations))
329+
330+
for _, destination := range destinations {
331+
targetRef := networkingv1alpha1ac.LoadBalancerTargetRef().
332+
WithName(destination.TargetRef.Name).
333+
WithUID(destination.TargetRef.UID)
334+
if destination.TargetRef.ProviderID != "" {
335+
targetRef = targetRef.WithProviderID(destination.TargetRef.ProviderID)
336+
}
337+
338+
destinationApplyConfigs = append(
339+
destinationApplyConfigs,
340+
networkingv1alpha1ac.LoadBalancerDestination().
341+
WithIP(destination.IP).
342+
WithTargetRef(targetRef),
343+
)
344+
}
345+
346+
return networkingv1alpha1ac.LoadBalancerRouting(
347+
loadBalancer.Name,
348+
o.ironcoreNamespace,
349+
).
350+
WithOwnerReferences(
351+
metav1ac.OwnerReference().
352+
WithAPIVersion(networkingv1alpha1.SchemeGroupVersion.String()).
353+
WithKind("LoadBalancer").
354+
WithName(loadBalancer.Name).
355+
WithUID(loadBalancer.UID),
356+
).
357+
WithNetworkRef(
358+
v1alpha1.LocalUIDReference{
359+
Name: network.Name,
360+
UID: network.UID,
361+
}).
362+
WithDestinations(destinationApplyConfigs...)
363+
}
364+
293365
func (o *ironcoreLoadBalancer) getLoadBalancerDestinationsForNodes(ctx context.Context, nodes []*v1.Node, networkName string) ([]networkingv1alpha1.LoadBalancerDestination, error) {
294366
var loadbalancerDestinations []networkingv1alpha1.LoadBalancerDestination
295367
for _, node := range nodes {

pkg/cloudprovider/ironcore/suite_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ var _ = BeforeSuite(func() {
8080
// Note that you must have the required binaries setup under the bin directory to perform
8181
// the tests directly. When we run make test it will be setup and used automatically.
8282
BinaryAssetsDirectory: filepath.Join("..", "..", "..", "bin", "k8s",
83-
fmt.Sprintf("1.34.0-%s-%s", runtime.GOOS, runtime.GOARCH)),
83+
fmt.Sprintf("1.35.0-%s-%s", runtime.GOOS, runtime.GOARCH)),
8484
}
8585
testEnvExt = &envtestext.EnvironmentExtensions{
8686
APIServiceDirectoryPaths: []string{

0 commit comments

Comments
 (0)