• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubeovn / kube-ovn / 13652314461

04 Mar 2025 11:07AM UTC coverage: 22.07% (+0.007%) from 22.063%
13652314461

push

github

web-flow
simple vip lable update and then update subnet status (#5036)

Signed-off-by: zbb88888 <jmdxjsjgcxy@gmail.com>

0 of 3 new or added lines in 1 file covered. (0.0%)

1 existing line in 1 file now uncovered.

10265 of 46512 relevant lines covered (22.07%)

0.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/pkg/controller/vip.go
1
package controller
2

3
import (
4
        "context"
5
        "encoding/json"
6
        "errors"
7
        "fmt"
8
        "slices"
9
        "strings"
10

11
        k8serrors "k8s.io/apimachinery/pkg/api/errors"
12
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13
        "k8s.io/apimachinery/pkg/types"
14
        "k8s.io/client-go/tools/cache"
15
        "k8s.io/klog/v2"
16
        "sigs.k8s.io/controller-runtime/pkg/client"
17
        "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
18

19
        kubeovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1"
20
        "github.com/kubeovn/kube-ovn/pkg/ovs"
21
        "github.com/kubeovn/kube-ovn/pkg/util"
22
)
23

24
func (c *Controller) enqueueAddVirtualIP(obj interface{}) {
×
25
        key := cache.MetaObjectToName(obj.(*kubeovnv1.Vip)).String()
×
26
        klog.Infof("enqueue add vip %s", key)
×
27
        c.addVirtualIPQueue.Add(key)
×
28
}
×
29

30
func (c *Controller) enqueueUpdateVirtualIP(oldObj, newObj interface{}) {
×
31
        oldVip := oldObj.(*kubeovnv1.Vip)
×
32
        newVip := newObj.(*kubeovnv1.Vip)
×
33
        key := cache.MetaObjectToName(newVip).String()
×
34
        if !newVip.DeletionTimestamp.IsZero() ||
×
35
                oldVip.Spec.MacAddress != newVip.Spec.MacAddress ||
×
36
                oldVip.Spec.ParentMac != newVip.Spec.ParentMac ||
×
37
                oldVip.Spec.ParentV4ip != newVip.Spec.ParentV4ip ||
×
38
                oldVip.Spec.V4ip != newVip.Spec.V4ip ||
×
39
                oldVip.Spec.V6ip != newVip.Spec.V6ip {
×
40
                klog.Infof("enqueue update vip %s", key)
×
41
                c.updateVirtualIPQueue.Add(key)
×
42
        }
×
43
        if !slices.Equal(oldVip.Spec.Selector, newVip.Spec.Selector) {
×
44
                klog.Infof("enqueue update virtual parents for %s", key)
×
45
                c.updateVirtualParentsQueue.Add(key)
×
46
        }
×
47
}
48

49
func (c *Controller) enqueueDelVirtualIP(obj interface{}) {
×
50
        vip := obj.(*kubeovnv1.Vip)
×
51
        key := cache.MetaObjectToName(vip).String()
×
52
        klog.Infof("enqueue del vip %s", key)
×
53
        c.delVirtualIPQueue.Add(vip)
×
54
}
×
55

56
func (c *Controller) handleAddVirtualIP(key string) error {
×
57
        cachedVip, err := c.virtualIpsLister.Get(key)
×
58
        if err != nil {
×
59
                if k8serrors.IsNotFound(err) {
×
60
                        return nil
×
61
                }
×
62
                klog.Error(err)
×
63
                return err
×
64
        }
65
        if cachedVip.Status.Mac != "" {
×
66
                // already ok
×
67
                return nil
×
68
        }
×
69
        klog.V(3).Infof("handle add vip %s", key)
×
70
        vip := cachedVip.DeepCopy()
×
71
        var sourceV4Ip, sourceV6Ip, v4ip, v6ip, mac, subnetName string
×
72
        subnetName = vip.Spec.Subnet
×
73
        if subnetName == "" {
×
74
                return fmt.Errorf("failed to create vip '%s', subnet should be set", key)
×
75
        }
×
76
        subnet, err := c.subnetsLister.Get(subnetName)
×
77
        if err != nil {
×
78
                klog.Errorf("failed to get subnet %s: %v", subnetName, err)
×
79
                return err
×
80
        }
×
81
        portName := ovs.PodNameToPortName(vip.Name, vip.Spec.Namespace, subnet.Spec.Provider)
×
82
        sourceV4Ip = vip.Spec.V4ip
×
83
        sourceV6Ip = vip.Spec.V6ip
×
84
        // v6 ip address can not use upper case
×
85
        if util.ContainsUppercase(vip.Spec.V6ip) {
×
86
                err := fmt.Errorf("vip %s v6 ip address %s can not contain upper case", vip.Name, vip.Spec.V6ip)
×
87
                klog.Error(err)
×
88
                return err
×
89
        }
×
90
        ipStr := util.GetStringIP(sourceV4Ip, sourceV6Ip)
×
91
        if ipStr != "" {
×
92
                v4ip, v6ip, mac, err = c.acquireStaticIPAddress(subnet.Name, vip.Name, portName, ipStr)
×
93
        } else {
×
94
                // Random allocate
×
95
                v4ip, v6ip, mac, err = c.acquireIPAddress(subnet.Name, vip.Name, portName)
×
96
        }
×
97

98
        if err != nil {
×
99
                klog.Error(err)
×
100
                return err
×
101
        }
×
102
        var parentV4ip, parentV6ip, parentMac string
×
103
        if vip.Spec.Type == util.SwitchLBRuleVip {
×
104
                // create a lsp use subnet gw mac, and set it option as arp_proxy
×
105
                lrpName := fmt.Sprintf("%s-%s", subnet.Spec.Vpc, subnet.Name)
×
106
                klog.Infof("get logical router port %s", lrpName)
×
107
                lrp, err := c.OVNNbClient.GetLogicalRouterPort(lrpName, false)
×
108
                if err != nil {
×
109
                        klog.Errorf("failed to get lrp %s: %v", lrpName, err)
×
110
                        return err
×
111
                }
×
112
                if lrp.MAC == "" {
×
113
                        err = fmt.Errorf("logical router port %s should have mac", lrpName)
×
114
                        klog.Error(err)
×
115
                        return err
×
116
                }
×
117
                mac = lrp.MAC
×
118
                ipStr := util.GetStringIP(v4ip, v6ip)
×
119
                if err := c.OVNNbClient.CreateLogicalSwitchPort(subnet.Name, portName, ipStr, mac, vip.Name, vip.Spec.Namespace, false, "", "", false, nil, subnet.Spec.Vpc); err != nil {
×
120
                        err = fmt.Errorf("failed to create lsp %s: %w", portName, err)
×
121
                        klog.Error(err)
×
122
                        return err
×
123
                }
×
124
                if err := c.OVNNbClient.SetLogicalSwitchPortArpProxy(portName, true); err != nil {
×
125
                        err = fmt.Errorf("failed to enable lsp arp proxy for vip %s: %w", portName, err)
×
126
                        klog.Error(err)
×
127
                        return err
×
128
                }
×
129
        }
130
        if vip.Spec.ParentMac != "" {
×
131
                if vip.Spec.Type == util.SwitchLBRuleVip {
×
132
                        err = errors.New("invalid usage of vip")
×
133
                        klog.Error(err)
×
134
                        return err
×
135
                }
×
136
                parentV4ip = vip.Spec.ParentV4ip
×
137
                parentV6ip = vip.Spec.ParentV6ip
×
138
                parentMac = vip.Spec.ParentMac
×
139
        }
140
        if err = c.createOrUpdateVipCR(key, vip.Spec.Namespace, subnet.Name, v4ip, v6ip, mac, parentV4ip, parentV6ip, parentMac); err != nil {
×
141
                klog.Errorf("failed to create or update vip '%s', %v", vip.Name, err)
×
142
                return err
×
143
        }
×
144
        if err := c.handleUpdateVirtualParents(key); err != nil {
×
145
                err := fmt.Errorf("error syncing virtual parents for vip '%s': %s", key, err.Error())
×
146
                klog.Error(err)
×
147
                return err
×
148
        }
×
149
        return nil
×
150
}
151

152
func (c *Controller) handleUpdateVirtualIP(key string) error {
×
153
        cachedVip, err := c.virtualIpsLister.Get(key)
×
154
        if err != nil {
×
155
                if k8serrors.IsNotFound(err) {
×
156
                        return nil
×
157
                }
×
158
                klog.Error(err)
×
159
                return err
×
160
        }
161
        vip := cachedVip.DeepCopy()
×
162
        // should delete
×
163
        if !vip.DeletionTimestamp.IsZero() {
×
164
                if err = c.handleDelVipFinalizer(key); err != nil {
×
165
                        klog.Errorf("failed to handle vip finalizer %v", err)
×
166
                        return err
×
167
                }
×
168
                return nil
×
169
        }
170
        // v6 ip address can not use upper case
171
        if util.ContainsUppercase(vip.Spec.V6ip) {
×
172
                err := fmt.Errorf("vip %s v6 ip address %s can not contain upper case", vip.Name, vip.Spec.V6ip)
×
173
                klog.Error(err)
×
174
                return err
×
175
        }
×
176
        // not support change
177
        if vip.Status.Mac != "" && vip.Status.Mac != vip.Spec.MacAddress {
×
178
                err = errors.New("not support change mac of vip")
×
179
                klog.Errorf("%v", err)
×
180
                return err
×
181
        }
×
182
        if vip.Status.V4ip != "" && vip.Status.V4ip != vip.Spec.V4ip {
×
183
                err = errors.New("not support change v4 ip of vip")
×
184
                klog.Errorf("%v", err)
×
185
                return err
×
186
        }
×
187
        if vip.Status.V6ip != "" && vip.Status.V6ip != vip.Spec.V6ip {
×
188
                err = errors.New("not support change v6 ip of vip")
×
189
                klog.Errorf("%v", err)
×
190
                return err
×
191
        }
×
192
        // should update
193
        if vip.Status.Mac == "" {
×
194
                // TODO:// add vip in its parent port aap list
×
195
                if err = c.createOrUpdateVipCR(key, vip.Spec.Namespace, vip.Spec.Subnet,
×
196
                        vip.Spec.V4ip, vip.Spec.V6ip, vip.Spec.MacAddress,
×
197
                        vip.Spec.ParentV4ip, vip.Spec.ParentV6ip, vip.Spec.MacAddress); err != nil {
×
198
                        klog.Error(err)
×
199
                        return err
×
200
                }
×
201
                ready := true
×
202
                if err = c.patchVipStatus(key, vip.Spec.V4ip, ready); err != nil {
×
203
                        klog.Error(err)
×
204
                        return err
×
205
                }
×
206
                if err = c.handleAddVipFinalizer(key); err != nil {
×
207
                        klog.Errorf("failed to handle vip finalizer %v", err)
×
208
                        return err
×
209
                }
×
210
        }
211
        return nil
×
212
}
213

214
func (c *Controller) handleDelVirtualIP(vip *kubeovnv1.Vip) error {
×
215
        klog.Infof("handle delete vip %s", vip.Name)
×
216
        // TODO:// clean vip in its parent port aap list
×
217
        if vip.Spec.Type == util.SwitchLBRuleVip {
×
218
                subnet, err := c.subnetsLister.Get(vip.Spec.Subnet)
×
219
                if err != nil {
×
220
                        klog.Errorf("failed to get subnet %s: %v", vip.Spec.Subnet, err)
×
221
                        return err
×
222
                }
×
223
                portName := ovs.PodNameToPortName(vip.Name, vip.Spec.Namespace, subnet.Spec.Provider)
×
224
                klog.Infof("delete vip arp proxy lsp %s", portName)
×
225
                if err := c.OVNNbClient.DeleteLogicalSwitchPort(portName); err != nil {
×
226
                        err = fmt.Errorf("failed to delete lsp %s: %w", vip.Name, err)
×
227
                        klog.Error(err)
×
228
                        return err
×
229
                }
×
230
        }
231
        // delete virtual ports
232
        if err := c.OVNNbClient.DeleteLogicalSwitchPort(vip.Name); err != nil {
×
233
                klog.Errorf("delete virtual logical switch port %s from logical switch %s: %v", vip.Name, vip.Spec.Subnet, err)
×
234
                return err
×
235
        }
×
236
        c.ipam.ReleaseAddressByPod(vip.Name, vip.Spec.Subnet)
×
237
        c.updateSubnetStatusQueue.Add(vip.Spec.Subnet)
×
238
        return nil
×
239
}
240

241
func (c *Controller) handleUpdateVirtualParents(key string) error {
×
242
        cachedVip, err := c.virtualIpsLister.Get(key)
×
243
        if err != nil {
×
244
                if k8serrors.IsNotFound(err) {
×
245
                        return nil
×
246
                }
×
247
                klog.Error(err)
×
248
                return err
×
249
        }
250
        // only pods in the same namespace as vip are allowed to use aap
251
        if (cachedVip.Status.V4ip == "" && cachedVip.Status.V6ip == "") || cachedVip.Spec.Namespace == "" {
×
252
                return nil
×
253
        }
×
254

255
        // add new virtual port if not exist
256
        ipStr := util.GetStringIP(cachedVip.Status.V4ip, cachedVip.Status.V6ip)
×
257
        if err = c.OVNNbClient.CreateVirtualLogicalSwitchPort(cachedVip.Name, cachedVip.Spec.Subnet, ipStr); err != nil {
×
258
                klog.Errorf("create virtual port with vip %s from logical switch %s: %v", cachedVip.Name, cachedVip.Spec.Subnet, err)
×
259
                return err
×
260
        }
×
261

262
        // update virtual parents
263
        if cachedVip.Spec.Type == util.SwitchLBRuleVip {
×
264
                // switch lb rule vip no need to have virtual parents
×
265
                return nil
×
266
        }
×
267

268
        // vip cloud use selector to select pods as its virtual parents
269
        selectors := make(map[string]string)
×
270
        for _, v := range cachedVip.Spec.Selector {
×
271
                parts := strings.Split(strings.TrimSpace(v), ":")
×
272
                if len(parts) != 2 {
×
273
                        continue
×
274
                }
275
                selectors[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
×
276
        }
277
        sel, _ := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{MatchLabels: selectors})
×
278
        pods, err := c.podsLister.Pods(cachedVip.Spec.Namespace).List(sel)
×
279
        if err != nil {
×
280
                klog.Errorf("failed to list pods that meet selector requirements, %v", err)
×
281
                return err
×
282
        }
×
283

284
        var virtualParents []string
×
285
        for _, pod := range pods {
×
286
                if pod.Annotations == nil {
×
287
                        // pod has no annotations
×
288
                        continue
×
289
                }
290
                if aaps := strings.Split(pod.Annotations[util.AAPsAnnotation], ","); !slices.Contains(aaps, cachedVip.Name) {
×
291
                        continue
×
292
                }
293
                podNets, err := c.getPodKubeovnNets(pod)
×
294
                if err != nil {
×
295
                        klog.Errorf("failed to get pod nets %v", err)
×
296
                }
×
297
                for _, podNet := range podNets {
×
298
                        if podNet.Subnet.Name == cachedVip.Spec.Subnet {
×
299
                                portName := ovs.PodNameToPortName(pod.Name, pod.Namespace, podNet.ProviderName)
×
300
                                virtualParents = append(virtualParents, portName)
×
301
                                key := cache.MetaObjectToName(pod).String()
×
302
                                klog.Infof("enqueue update pod security for %s", key)
×
303
                                c.updatePodSecurityQueue.Add(key)
×
304
                                break
×
305
                        }
306
                }
307
        }
308

309
        parents := strings.Join(virtualParents, ",")
×
310
        if err = c.OVNNbClient.SetVirtualLogicalSwitchPortVirtualParents(cachedVip.Name, parents); err != nil {
×
311
                klog.Errorf("set vip %s virtual parents %s: %v", cachedVip.Name, parents, err)
×
312
                return err
×
313
        }
×
314

315
        return nil
×
316
}
317

318
func (c *Controller) createOrUpdateVipCR(key, ns, subnet, v4ip, v6ip, mac, pV4ip, pV6ip, pmac string) error {
×
319
        vipCR, err := c.virtualIpsLister.Get(key)
×
320
        if err != nil {
×
321
                if k8serrors.IsNotFound(err) {
×
322
                        if _, err := c.config.KubeOvnClient.KubeovnV1().Vips().Create(context.Background(), &kubeovnv1.Vip{
×
323
                                ObjectMeta: metav1.ObjectMeta{
×
324
                                        Name: key,
×
325
                                        Labels: map[string]string{
×
326
                                                util.SubnetNameLabel: subnet,
×
327
                                                util.IPReservedLabel: "",
×
328
                                        },
×
329
                                        Namespace: ns,
×
330
                                },
×
331
                                Spec: kubeovnv1.VipSpec{
×
332
                                        Namespace:  ns,
×
333
                                        Subnet:     subnet,
×
334
                                        V4ip:       v4ip,
×
335
                                        V6ip:       v6ip,
×
336
                                        MacAddress: mac,
×
337
                                        ParentV4ip: pV4ip,
×
338
                                        ParentV6ip: pV6ip,
×
339
                                        ParentMac:  pmac,
×
340
                                },
×
341
                        }, metav1.CreateOptions{}); err != nil {
×
342
                                err := fmt.Errorf("failed to create crd vip '%s', %w", key, err)
×
343
                                klog.Error(err)
×
344
                                return err
×
345
                        }
×
346
                } else {
×
347
                        err := fmt.Errorf("failed to get crd vip '%s', %w", key, err)
×
348
                        klog.Error(err)
×
349
                        return err
×
350
                }
×
351
        } else {
×
352
                vip := vipCR.DeepCopy()
×
353
                if vip.Status.Mac == "" && mac != "" {
×
354
                        // vip not support to update, just delete and create
×
355
                        vip.Spec.Namespace = ns
×
356
                        vip.Spec.V4ip = v4ip
×
357
                        vip.Spec.V6ip = v6ip
×
358
                        vip.Spec.MacAddress = mac
×
359
                        vip.Spec.ParentV4ip = pV4ip
×
360
                        vip.Spec.ParentV6ip = pV6ip
×
361
                        vip.Spec.ParentMac = pmac
×
362

×
363
                        vip.Status.Ready = true
×
364
                        vip.Status.V4ip = v4ip
×
365
                        vip.Status.V6ip = v6ip
×
366
                        vip.Status.Mac = mac
×
367
                        vip.Status.Pv4ip = pV4ip
×
368
                        vip.Status.Pv6ip = pV6ip
×
369
                        vip.Status.Pmac = pmac
×
370
                        vip.Status.Type = vip.Spec.Type
×
371
                        if _, err := c.config.KubeOvnClient.KubeovnV1().Vips().Update(context.Background(), vip, metav1.UpdateOptions{}); err != nil {
×
372
                                err := fmt.Errorf("failed to update vip '%s', %w", key, err)
×
373
                                klog.Error(err)
×
374
                                return err
×
375
                        }
×
376
                }
377
                var needUpdateLabel bool
×
378
                var op string
×
379
                if len(vip.Labels) == 0 {
×
380
                        op = "add"
×
381
                        vip.Labels = map[string]string{
×
382
                                util.SubnetNameLabel: subnet,
×
383
                                util.IPReservedLabel: "",
×
384
                        }
×
385
                        needUpdateLabel = true
×
386
                }
×
NEW
387
                if _, ok := vip.Labels[util.SubnetNameLabel]; !ok {
×
388
                        op = "add"
×
NEW
389
                        vip.Labels[util.SubnetNameLabel] = subnet
×
390
                        vip.Labels[util.IPReservedLabel] = ""
×
391
                        needUpdateLabel = true
×
392
                }
×
393
                if needUpdateLabel {
×
394
                        patchPayloadTemplate := `[{ "op": "%s", "path": "/metadata/labels", "value": %s }]`
×
395
                        raw, _ := json.Marshal(vip.Labels)
×
396
                        patchPayload := fmt.Sprintf(patchPayloadTemplate, op, raw)
×
397
                        if _, err := c.config.KubeOvnClient.KubeovnV1().Vips().Patch(context.Background(), vip.Name, types.JSONPatchType,
×
398
                                []byte(patchPayload), metav1.PatchOptions{}); err != nil {
×
399
                                klog.Errorf("failed to patch label for vip '%s', %v", vip.Name, err)
×
400
                                return err
×
401
                        }
×
402
                }
403
        }
NEW
404
        c.updateSubnetStatusQueue.Add(subnet)
×
UNCOV
405
        return nil
×
406
}
407

408
func (c *Controller) patchVipStatus(key, v4ip string, ready bool) error {
×
409
        oriVip, err := c.virtualIpsLister.Get(key)
×
410
        if err != nil {
×
411
                if k8serrors.IsNotFound(err) {
×
412
                        return nil
×
413
                }
×
414
                klog.Error(err)
×
415
                return err
×
416
        }
417
        vip := oriVip.DeepCopy()
×
418
        var changed bool
×
419
        if vip.Status.Ready != ready {
×
420
                vip.Status.Ready = ready
×
421
                changed = true
×
422
        }
×
423

424
        if ready && v4ip != "" && vip.Status.V4ip != v4ip {
×
425
                vip.Status.V4ip = v4ip
×
426
                changed = true
×
427
        }
×
428

429
        if changed {
×
430
                if _, err = c.config.KubeOvnClient.KubeovnV1().Vips().Update(context.Background(), vip, metav1.UpdateOptions{}); err != nil {
×
431
                        klog.Errorf("failed to update status for vip '%s', %v", key, err)
×
432
                        return err
×
433
                }
×
434
        }
435
        return nil
×
436
}
437

438
func (c *Controller) podReuseVip(key, portName string, keepVIP bool) error {
×
439
        // when pod use static vip, label vip reserved for pod
×
440
        oriVip, err := c.virtualIpsLister.Get(key)
×
441
        if err != nil {
×
442
                if k8serrors.IsNotFound(err) {
×
443
                        return nil
×
444
                }
×
445
                klog.Error(err)
×
446
                return err
×
447
        }
448
        vip := oriVip.DeepCopy()
×
449
        var op string
×
450

×
451
        if vip.Labels[util.IPReservedLabel] != "" {
×
452
                if keepVIP && vip.Labels[util.IPReservedLabel] == portName {
×
453
                        return nil
×
454
                }
×
455
                return fmt.Errorf("vip '%s' is in use by pod %s", vip.Name, vip.Labels[util.IPReservedLabel])
×
456
        }
457
        op = "replace"
×
458
        vip.Labels[util.IPReservedLabel] = portName
×
459
        patchPayloadTemplate := `[{ "op": "%s", "path": "/metadata/labels", "value": %s }]`
×
460
        raw, _ := json.Marshal(vip.Labels)
×
461
        patchPayload := fmt.Sprintf(patchPayloadTemplate, op, raw)
×
462
        if _, err = c.config.KubeOvnClient.KubeovnV1().Vips().Patch(context.Background(), vip.Name, types.JSONPatchType, []byte(patchPayload), metav1.PatchOptions{}); err != nil {
×
463
                klog.Errorf("failed to patch label for vip '%s', %v", vip.Name, err)
×
464
                return err
×
465
        }
×
466
        c.ipam.ReleaseAddressByPod(key, vip.Spec.Subnet)
×
467
        c.updateSubnetStatusQueue.Add(vip.Spec.Subnet)
×
468
        return nil
×
469
}
470

471
func (c *Controller) releaseVip(key string) error {
×
472
        // clean vip label when pod delete
×
473
        oriVip, err := c.virtualIpsLister.Get(key)
×
474
        if err != nil {
×
475
                if k8serrors.IsNotFound(err) {
×
476
                        return nil
×
477
                }
×
478
                klog.Error(err)
×
479
                return err
×
480
        }
481
        vip := oriVip.DeepCopy()
×
482
        var needUpdateLabel bool
×
483
        var op string
×
484
        if vip.Labels[util.IPReservedLabel] == "" {
×
485
                return nil
×
486
        }
×
487
        op = "replace"
×
488
        vip.Labels[util.IPReservedLabel] = ""
×
489
        needUpdateLabel = true
×
490
        if needUpdateLabel {
×
491
                klog.V(3).Infof("clean reserved label from vip %s", key)
×
492
                patchPayloadTemplate := `[{ "op": "%s", "path": "/metadata/labels", "value": %s }]`
×
493
                raw, _ := json.Marshal(vip.Labels)
×
494
                patchPayload := fmt.Sprintf(patchPayloadTemplate, op, raw)
×
495
                if _, err := c.config.KubeOvnClient.KubeovnV1().Vips().Patch(context.Background(), vip.Name,
×
496
                        types.JSONPatchType, []byte(patchPayload), metav1.PatchOptions{}); err != nil {
×
497
                        klog.Errorf("failed to patch label for vip '%s', %v", vip.Name, err)
×
498
                        return err
×
499
                }
×
500
                mac := &vip.Status.Mac
×
501
                if vip.Status.Mac == "" {
×
502
                        mac = nil
×
503
                }
×
504
                if _, _, _, err = c.ipam.GetStaticAddress(key, vip.Name, vip.Status.V4ip, mac, vip.Spec.Subnet, false); err != nil {
×
505
                        klog.Errorf("failed to recover IPAM from vip CR %s: %v", vip.Name, err)
×
506
                }
×
507
                c.updateSubnetStatusQueue.Add(vip.Spec.Subnet)
×
508
        }
509
        return nil
×
510
}
511

512
func (c *Controller) handleAddVipFinalizer(key string) error {
×
513
        cachedVip, err := c.virtualIpsLister.Get(key)
×
514
        if err != nil {
×
515
                if k8serrors.IsNotFound(err) {
×
516
                        return nil
×
517
                }
×
518
                klog.Error(err)
×
519
                return err
×
520
        }
521
        if !cachedVip.DeletionTimestamp.IsZero() || len(cachedVip.GetFinalizers()) != 0 {
×
522
                return nil
×
523
        }
×
524
        newVip := cachedVip.DeepCopy()
×
525
        controllerutil.AddFinalizer(newVip, util.KubeOVNControllerFinalizer)
×
526
        patch, err := util.GenerateMergePatchPayload(cachedVip, newVip)
×
527
        if err != nil {
×
528
                klog.Errorf("failed to generate patch payload for ovn eip '%s', %v", cachedVip.Name, err)
×
529
                return err
×
530
        }
×
531
        if _, err := c.config.KubeOvnClient.KubeovnV1().Vips().Patch(context.Background(), cachedVip.Name,
×
532
                types.MergePatchType, patch, metav1.PatchOptions{}, ""); err != nil {
×
533
                if k8serrors.IsNotFound(err) {
×
534
                        return nil
×
535
                }
×
536
                klog.Errorf("failed to add finalizer for vip '%s', %v", cachedVip.Name, err)
×
537
                return err
×
538
        }
539
        return nil
×
540
}
541

542
func (c *Controller) handleDelVipFinalizer(key string) error {
×
543
        cachedVip, err := c.virtualIpsLister.Get(key)
×
544
        if err != nil {
×
545
                if k8serrors.IsNotFound(err) {
×
546
                        return nil
×
547
                }
×
548
                klog.Error(err)
×
549
                return err
×
550
        }
551
        if len(cachedVip.GetFinalizers()) == 0 {
×
552
                return nil
×
553
        }
×
554
        newVip := cachedVip.DeepCopy()
×
555
        controllerutil.RemoveFinalizer(newVip, util.KubeOVNControllerFinalizer)
×
556
        patch, err := util.GenerateMergePatchPayload(cachedVip, newVip)
×
557
        if err != nil {
×
558
                klog.Errorf("failed to generate patch payload for ovn eip '%s', %v", cachedVip.Name, err)
×
559
                return err
×
560
        }
×
561
        if _, err := c.config.KubeOvnClient.KubeovnV1().Vips().Patch(context.Background(), cachedVip.Name,
×
562
                types.MergePatchType, patch, metav1.PatchOptions{}, ""); err != nil {
×
563
                if k8serrors.IsNotFound(err) {
×
564
                        return nil
×
565
                }
×
566
                klog.Errorf("failed to remove finalizer from vip '%s', %v", cachedVip.Name, err)
×
567
                return err
×
568
        }
569
        return nil
×
570
}
571

572
func (c *Controller) syncVipFinalizer(cl client.Client) error {
×
573
        // migrate depreciated finalizer to new finalizer
×
574
        vips := &kubeovnv1.VipList{}
×
575
        return migrateFinalizers(cl, vips, func(i int) (client.Object, client.Object) {
×
576
                if i < 0 || i >= len(vips.Items) {
×
577
                        return nil, nil
×
578
                }
×
579
                return vips.Items[i].DeepCopy(), vips.Items[i].DeepCopy()
×
580
        })
581
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc