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

k8snetworkplumbingwg / sriov-network-operator / 28739567397

05 Jul 2026 11:41AM UTC coverage: 63.991% (+0.2%) from 63.812%
28739567397

Pull #1010

github

web-flow
Merge adac6af62 into fe2b336cb
Pull Request #1010: Conditions/network crds

187 of 252 new or added lines in 10 files covered. (74.21%)

7 existing lines in 1 file now uncovered.

9895 of 15463 relevant lines covered (63.99%)

0.71 hits per line

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

73.54
/controllers/generic_network_controller.go
1
/*
2
Copyright 2021.
3

4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7

8
    http://www.apache.org/licenses/LICENSE-2.0
9

10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16

17
package controllers
18

19
import (
20
        "context"
21
        "fmt"
22

23
        netattdefv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
24
        corev1 "k8s.io/api/core/v1"
25
        "k8s.io/apimachinery/pkg/api/equality"
26
        "k8s.io/apimachinery/pkg/api/errors"
27
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28
        uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
29
        "k8s.io/apimachinery/pkg/runtime"
30
        "k8s.io/apimachinery/pkg/types"
31
        "k8s.io/client-go/util/workqueue"
32
        ctrl "sigs.k8s.io/controller-runtime"
33
        "sigs.k8s.io/controller-runtime/pkg/client"
34
        "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
35
        "sigs.k8s.io/controller-runtime/pkg/event"
36
        "sigs.k8s.io/controller-runtime/pkg/handler"
37
        "sigs.k8s.io/controller-runtime/pkg/log"
38
        "sigs.k8s.io/controller-runtime/pkg/reconcile"
39

40
        sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1"
41
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts"
42
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/status"
43
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils"
44
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars"
45
)
46

47
type NetworkCRInstance interface {
48
        client.Object
49
        // renders NetAttDef from the network instance
50
        RenderNetAttDef() (*uns.Unstructured, error)
51
        // return name of the target namespace for the network
52
        NetworkNamespace() string
53
}
54

55
// interface which controller should implement to be compatible with genericNetworkReconciler
56
type networkController interface {
57
        reconcile.Reconciler
58
        // GetObject should return CR type which implements networkCRInstance
59
        // interface
60
        GetObject() NetworkCRInstance
61
        // should return CR list type
62
        GetObjectList() client.ObjectList
63
        // should return name of the controller
64
        Name() string
65
}
66

67
func newGenericNetworkReconciler(c client.Client, s *runtime.Scheme, controller networkController, statusPatcher status.Interface) *genericNetworkReconciler {
1✔
68
        return &genericNetworkReconciler{
1✔
69
                Client:        c,
1✔
70
                Scheme:        s,
1✔
71
                controller:    controller,
1✔
72
                statusPatcher: statusPatcher,
1✔
73
        }
1✔
74
}
1✔
75

76
// genericNetworkReconciler provide common code for all network controllers
77
type genericNetworkReconciler struct {
78
        client.Client
79
        Scheme        *runtime.Scheme
80
        controller    networkController
81
        statusPatcher status.Interface
82
}
83

84
func (r *genericNetworkReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
1✔
85
        reqLogger := log.FromContext(ctx).WithValues(r.controller.Name(), req.NamespacedName)
1✔
86

1✔
87
        reqLogger.Info("Reconciling " + r.controller.Name())
1✔
88
        var err error
1✔
89

1✔
90
        // Fetch instance of the network object
1✔
91
        instance := r.controller.GetObject()
1✔
92
        err = r.Get(ctx, req.NamespacedName, instance)
1✔
93
        if err != nil {
2✔
94
                if errors.IsNotFound(err) {
2✔
95
                        // Request object not found, could have been deleted after reconcile request.
1✔
96
                        // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
1✔
97
                        // Return and don't requeue
1✔
98
                        return reconcile.Result{}, nil
1✔
99
                }
1✔
100
                // Error reading the object - requeue the request.
101
                return reconcile.Result{}, err
×
102
        }
103

104
        if instance == nil {
1✔
105
                // Request object not found, could have been deleted after reconcile request.
×
106
                // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
×
107
                // Return and don't requeue
×
108
                return reconcile.Result{}, nil
×
109
        }
×
110

111
        if instance.NetworkNamespace() != "" && instance.GetNamespace() != vars.Namespace {
2✔
112
                errMsg := fmt.Errorf("spec.networkNamespace cannot be set when the resource is not in the operator namespace (%s)", vars.Namespace)
1✔
113
                reqLogger.Error(
1✔
114
                        errMsg,
1✔
115
                        ".spec.networkNamespace can't be specified if the resource belongs to a namespace other than the operator's",
1✔
116
                        "operatorNamespace", vars.Namespace,
1✔
117
                        ".metadata.namespace", instance.GetNamespace(),
1✔
118
                        ".spec.networkNamespace", instance.NetworkNamespace(),
1✔
119
                )
1✔
120
                err = r.statusPatcher.ApplyCondition(ctx, instance,
1✔
121
                        status.NewCondition(sriovnetworkv1.ConditionReady, metav1.ConditionFalse,
1✔
122
                                sriovnetworkv1.ReasonNetworkAttachmentDefInvalid, errMsg.Error(), instance.GetGeneration()))
1✔
123
                if err != nil {
1✔
NEW
124
                        reqLogger.Error(err, "Failed to apply status conditions")
×
NEW
125
                }
×
126
                return reconcile.Result{}, err
1✔
127
        }
128

129
        // examine DeletionTimestamp to determine if object is under deletion
130
        if instance.GetDeletionTimestamp().IsZero() {
2✔
131
                // The object is not being deleted, so if it does not have our finalizer,
1✔
132
                // then lets add the finalizer and update the object. This is equivalent
1✔
133
                // registering our finalizer.
1✔
134
                err = r.updateFinalizers(ctx, instance)
1✔
135
                if err != nil {
1✔
UNCOV
136
                        return reconcile.Result{}, err
×
UNCOV
137
                }
×
138
        } else {
1✔
139
                // The object is being deleted
1✔
140
                err = r.cleanResourcesAndFinalizers(ctx, instance)
1✔
141
                return reconcile.Result{}, err
1✔
142
        }
1✔
143
        raw, err := instance.RenderNetAttDef()
1✔
144
        if err != nil {
1✔
NEW
145
                if updateErr := r.statusPatcher.ApplyCondition(ctx, instance,
×
NEW
146
                        status.NewCondition(sriovnetworkv1.ConditionReady, metav1.ConditionFalse,
×
NEW
147
                                sriovnetworkv1.ReasonNetworkAttachmentDefInvalid, err.Error(), instance.GetGeneration())); updateErr != nil {
×
NEW
148
                        reqLogger.Error(updateErr, "Failed to apply status conditions")
×
NEW
149
                }
×
150
                return reconcile.Result{}, err
×
151
        }
152
        netAttDef := &netattdefv1.NetworkAttachmentDefinition{}
1✔
153
        err = r.Scheme.Convert(raw, netAttDef, nil)
1✔
154
        if err != nil {
1✔
155
                return reconcile.Result{}, err
×
156
        }
×
157
        // format CNI config json in CR for easier readability
158
        netAttDef.Spec.Config, err = formatJSON(netAttDef.Spec.Config)
1✔
159
        if err != nil {
1✔
160
                reqLogger.Error(err, "Couldn't process rendered NetworkAttachmentDefinition config", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
×
161
                return reconcile.Result{}, err
×
162
        }
×
163
        if lnns, ok := instance.GetAnnotations()[sriovnetworkv1.LASTNETWORKNAMESPACE]; ok && netAttDef.GetNamespace() != lnns {
2✔
164
                err = r.Delete(ctx, &netattdefv1.NetworkAttachmentDefinition{
1✔
165
                        ObjectMeta: metav1.ObjectMeta{
1✔
166
                                Name:      instance.GetName(),
1✔
167
                                Namespace: lnns,
1✔
168
                        },
1✔
169
                })
1✔
170
                if err != nil {
2✔
171
                        if !errors.IsNotFound(err) {
1✔
UNCOV
172
                                reqLogger.Error(err, "Couldn't delete NetworkAttachmentDefinition CR", "Namespace", lnns, "Name", instance.GetName())
×
UNCOV
173
                                return reconcile.Result{}, err
×
UNCOV
174
                        }
×
175
                        reqLogger.Info("Old NetworkAttachmentDefinition not found, skipping deletion", "Namespace", lnns, "Name", instance.GetName())
1✔
176
                }
177
                // Clear the stale annotation so we don't retry deletion.
178
                // It will be re-set at creation time (L192).
179
                if err := utils.AnnotateObject(ctx, instance, sriovnetworkv1.LASTNETWORKNAMESPACE, "", r.Client); err != nil {
1✔
180
                        reqLogger.Error(err, "Couldn't clear LASTNETWORKNAMESPACE annotation", "Name", instance.GetName())
×
181
                        return reconcile.Result{}, err
×
182
                }
×
183
        }
184

185
        if instance.GetNamespace() == netAttDef.Namespace {
2✔
186
                // If the NetAttachDef is in the same namespace of the resource, then we can leverage the OwnerReference field for garbage collector
1✔
187
                if err := controllerutil.SetOwnerReference(instance, netAttDef, r.Scheme); err != nil {
1✔
188
                        return reconcile.Result{}, err
×
189
                }
×
190
        }
191

192
        // Check if this NetworkAttachmentDefinition already exists
193
        found := &netattdefv1.NetworkAttachmentDefinition{}
1✔
194
        err = r.Get(ctx, types.NamespacedName{Name: netAttDef.Name, Namespace: netAttDef.Namespace}, found)
1✔
195
        if err != nil {
2✔
196
                if errors.IsNotFound(err) {
2✔
197
                        targetNamespace := &corev1.Namespace{}
1✔
198
                        err = r.Get(ctx, types.NamespacedName{Name: netAttDef.Namespace}, targetNamespace)
1✔
199
                        if errors.IsNotFound(err) {
2✔
200
                                reqLogger.Info("Target namespace doesn't exist, NetworkAttachmentDefinition will be created when namespace is available", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
1✔
201
                                if updateErr := r.statusPatcher.ApplyCondition(ctx, instance,
1✔
202
                                        status.NewCondition(sriovnetworkv1.ConditionReady, metav1.ConditionFalse,
1✔
203
                                                sriovnetworkv1.ReasonNamespaceNotFound, fmt.Sprintf("target namespace %q does not exist", netAttDef.Namespace), instance.GetGeneration())); updateErr != nil {
1✔
NEW
204
                                        reqLogger.Error(updateErr, "Failed to apply status conditions")
×
NEW
205
                                        return reconcile.Result{}, updateErr
×
NEW
206
                                }
×
207
                                return reconcile.Result{}, nil
1✔
208
                        }
209

210
                        reqLogger.Info("NetworkAttachmentDefinition CR not exist, creating")
1✔
211
                        err = r.Create(ctx, netAttDef)
1✔
212
                        if err != nil {
1✔
NEW
213
                                if updateErr := r.statusPatcher.ApplyCondition(ctx, instance,
×
NEW
214
                                        status.NewCondition(sriovnetworkv1.ConditionReady, metav1.ConditionFalse,
×
NEW
215
                                                sriovnetworkv1.ReasonNetworkAttachmentDefInvalid, err.Error(), instance.GetGeneration())); updateErr != nil {
×
NEW
216
                                        reqLogger.Error(updateErr, "Failed to apply status conditions")
×
NEW
217
                                }
×
218
                                reqLogger.Error(err, "Couldn't create NetworkAttachmentDefinition CR", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
×
219
                                return reconcile.Result{}, err
×
220
                        }
221

222
                        err = utils.AnnotateObject(ctx, instance, sriovnetworkv1.LASTNETWORKNAMESPACE, netAttDef.Namespace, r.Client)
1✔
223
                        if err != nil {
1✔
224
                                return reconcile.Result{}, err
×
225
                        }
×
226

227
                        if updateErr := r.statusPatcher.ApplyCondition(ctx, instance,
1✔
228
                                status.NewCondition(sriovnetworkv1.ConditionReady, metav1.ConditionTrue,
1✔
229
                                        sriovnetworkv1.ReasonNetworkReady, "NetworkAttachmentDefinition is provisioned and ready", instance.GetGeneration())); updateErr != nil {
1✔
NEW
230
                                reqLogger.Error(updateErr, "Failed to apply status conditions")
×
NEW
231
                                return reconcile.Result{}, updateErr
×
NEW
232
                        }
×
233
                } else {
×
234
                        reqLogger.Error(err, "Couldn't get NetworkAttachmentDefinition CR", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
×
NEW
235
                        if updateErr := r.statusPatcher.ApplyCondition(ctx, instance,
×
NEW
236
                                status.NewCondition(sriovnetworkv1.ConditionReady, metav1.ConditionFalse,
×
NEW
237
                                        sriovnetworkv1.ReasonNetworkAttachmentDefNotFound, err.Error(), instance.GetGeneration())); updateErr != nil {
×
NEW
238
                                reqLogger.Error(updateErr, "Failed to apply status conditions")
×
NEW
239
                        }
×
240
                        return reconcile.Result{}, err
×
241
                }
242
        } else {
1✔
243
                reqLogger.Info("NetworkAttachmentDefinition CR already exist")
1✔
244

1✔
245
                foundOwner := found.GetAnnotations()[consts.OwnerRefAnnotation]
1✔
246
                expectedOwner := netAttDef.GetAnnotations()[consts.OwnerRefAnnotation]
1✔
247

1✔
248
                // Note for the future: the `foundOwner != ""` condition can be removed to make the operator not touching the NetworkAttachmentDefinition created
1✔
249
                // by the user.
1✔
250
                if foundOwner != "" && foundOwner != expectedOwner {
2✔
251
                        reqLogger.Info("A NetworkAttachmentDefinition with the same name already exists and it does not belong to this resource",
1✔
252
                                "Namespace", netAttDef.Namespace, "Name", netAttDef.Name,
1✔
253
                                "CurrentOwner", foundOwner, "ExpectedOwner", expectedOwner,
1✔
254
                        )
1✔
255
                        if updateErr := r.statusPatcher.ApplyCondition(ctx, instance,
1✔
256
                                status.NewCondition(sriovnetworkv1.ConditionReady, metav1.ConditionFalse,
1✔
257
                                        sriovnetworkv1.ReasonNetworkAttachmentDefInvalid,
1✔
258
                                        fmt.Sprintf("NetworkAttachmentDefinition '%s/%s' already exists and is owned by %s", netAttDef.Namespace, netAttDef.Name, foundOwner),
1✔
259
                                        instance.GetGeneration())); updateErr != nil {
1✔
NEW
260
                                reqLogger.Error(updateErr, "Failed to apply status conditions")
×
NEW
261
                                return reconcile.Result{}, updateErr
×
NEW
262
                        }
×
263
                        return reconcile.Result{}, nil
1✔
264
                }
265

266
                if !equality.Semantic.DeepEqual(found.Spec, netAttDef.Spec) || !equality.Semantic.DeepEqual(found.GetAnnotations(), netAttDef.GetAnnotations()) {
2✔
267
                        reqLogger.Info("Update NetworkAttachmentDefinition CR", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
1✔
268
                        netAttDef.SetResourceVersion(found.GetResourceVersion())
1✔
269

1✔
270
                        err = r.Update(ctx, netAttDef)
1✔
271
                        if err != nil {
1✔
272
                                reqLogger.Error(err, "Couldn't update NetworkAttachmentDefinition CR", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
×
NEW
273
                                if updateErr := r.statusPatcher.ApplyCondition(ctx, instance,
×
NEW
274
                                        status.NewCondition(sriovnetworkv1.ConditionReady, metav1.ConditionFalse,
×
NEW
275
                                                sriovnetworkv1.ReasonNetworkAttachmentDefInvalid, err.Error(), instance.GetGeneration())); updateErr != nil {
×
NEW
276
                                        reqLogger.Error(updateErr, "Failed to apply status conditions")
×
NEW
277
                                }
×
278
                                return reconcile.Result{}, err
×
279
                        }
280
                }
281

282
                if err := r.statusPatcher.ApplyCondition(ctx, instance,
1✔
283
                        status.NewCondition(sriovnetworkv1.ConditionReady, metav1.ConditionTrue,
1✔
284
                                sriovnetworkv1.ReasonNetworkReady, "NetworkAttachmentDefinition is provisioned and ready", instance.GetGeneration())); err != nil {
1✔
NEW
285
                        reqLogger.Error(err, "Failed to apply status conditions")
×
NEW
286
                        return reconcile.Result{}, err
×
NEW
287
                }
×
288
        }
289

290
        return ctrl.Result{}, nil
1✔
291
}
292

293
// SetupWithManager sets up the controller with the Manager.
294
func (r *genericNetworkReconciler) SetupWithManager(mgr ctrl.Manager) error {
1✔
295
        // Reconcile when the target namespace is created after the network object.
1✔
296
        namespaceHandler := handler.Funcs{
1✔
297
                CreateFunc: r.namespaceHandlerCreate,
1✔
298
        }
1✔
299
        return ctrl.NewControllerManagedBy(mgr).
1✔
300
                For(r.controller.GetObject()).
1✔
301
                Watches(&netattdefv1.NetworkAttachmentDefinition{}, handler.EnqueueRequestsFromMapFunc(r.handleNetAttDef)).
1✔
302
                Watches(&corev1.Namespace{}, &namespaceHandler).
1✔
303
                Complete(r.controller)
1✔
304
}
1✔
305

306
func (r *genericNetworkReconciler) handleNetAttDef(ctx context.Context, obj client.Object) []reconcile.Request {
1✔
307
        ret := []reconcile.Request{}
1✔
308
        instance := r.controller.GetObject()
1✔
309
        nadNamespacedName := types.NamespacedName{Namespace: obj.GetNamespace(), Name: obj.GetName()}
1✔
310

1✔
311
        err := r.Get(ctx, nadNamespacedName, instance)
1✔
312
        if err == nil {
2✔
313
                // Found a NetworkObject in the same namespace as the NetworkAttachmentDefinition, reconcile it
1✔
314
                ret = append(ret, reconcile.Request{NamespacedName: nadNamespacedName})
1✔
315
        } else if !errors.IsNotFound(err) {
2✔
316
                log.Log.WithName(r.controller.Name()+" handleNetAttDef").Error(err, "can't get object", "object", nadNamespacedName)
×
317
        }
×
318

319
        // Not found, try to find the NetworkObject in the operator's namespace
320
        operatorNamespacedName := types.NamespacedName{Namespace: vars.Namespace, Name: obj.GetName()}
1✔
321
        err = r.Get(ctx, operatorNamespacedName, instance)
1✔
322
        if err == nil {
2✔
323
                // Found a NetworkObject in the operator's namespace, reconcile it
1✔
324
                ret = append(ret, reconcile.Request{NamespacedName: operatorNamespacedName})
1✔
325
        } else if !errors.IsNotFound(err) {
2✔
326
                log.Log.WithName(r.controller.Name()+" handleNetAttDef").Error(err, "can't get object", "object", operatorNamespacedName)
×
327
        }
×
328

329
        return ret
1✔
330
}
331

332
func (r *genericNetworkReconciler) namespaceHandlerCreate(ctx context.Context, e event.TypedCreateEvent[client.Object], w workqueue.TypedRateLimitingInterface[reconcile.Request]) {
1✔
333
        networkList := r.controller.GetObjectList()
1✔
334
        err := r.List(ctx,
1✔
335
                networkList,
1✔
336
                client.MatchingFields{"spec.networkNamespace": e.Object.GetName()},
1✔
337
        )
1✔
338
        logger := log.Log.WithName(r.controller.Name() + " reconciler")
1✔
339
        if err != nil {
1✔
340
                logger.Info("Can't list networks for namespace", "resource", e.Object.GetName(), "error", err)
×
341
                return
×
342
        }
×
343
        unsContent, err := runtime.DefaultUnstructuredConverter.ToUnstructured(networkList)
1✔
344
        if err != nil {
1✔
345
                logger.Info("Can't convert network list to unstructured object", "resource", e.Object.GetName(), "error", err)
×
346
                return
×
347
        }
×
348
        unsList := &uns.Unstructured{}
1✔
349
        unsList.SetUnstructuredContent(unsContent)
1✔
350
        _ = unsList.EachListItem(func(o runtime.Object) error {
2✔
351
                unsObj := o.(*uns.Unstructured)
1✔
352
                w.Add(reconcile.Request{NamespacedName: types.NamespacedName{
1✔
353
                        Namespace: unsObj.GetNamespace(),
1✔
354
                        Name:      unsObj.GetName(),
1✔
355
                }})
1✔
356
                return nil
1✔
357
        })
1✔
358
}
359

360
// deleteNetAttDef deletes the generated net-att-def CR
361
func (r *genericNetworkReconciler) deleteNetAttDef(ctx context.Context, cr NetworkCRInstance) error {
1✔
362
        // Fetch the NetworkAttachmentDefinition instance
1✔
363
        namespace := cr.NetworkNamespace()
1✔
364
        if namespace == "" {
2✔
365
                namespace = cr.GetNamespace()
1✔
366
        }
1✔
367
        instance := &netattdefv1.NetworkAttachmentDefinition{ObjectMeta: metav1.ObjectMeta{Name: cr.GetName(), Namespace: namespace}}
1✔
368
        err := r.Delete(ctx, instance)
1✔
369
        if err != nil {
2✔
370
                if errors.IsNotFound(err) {
2✔
371
                        return nil
1✔
372
                }
1✔
373
                return err
1✔
374
        }
375
        return nil
1✔
376
}
377

378
func (r *genericNetworkReconciler) updateFinalizers(ctx context.Context, instance NetworkCRInstance) error {
1✔
379
        if instance.GetNamespace() != vars.Namespace {
2✔
380
                // If the resource is in a namespace different than the operator one, then the NetworkAttachmentDefinition will
1✔
381
                // be created in the same namespace and its deletion can be handled by OwnerReferences. There is no need for finalizers
1✔
382
                return nil
1✔
383
        }
1✔
384

385
        instanceFinalizers := instance.GetFinalizers()
1✔
386
        if !sriovnetworkv1.StringInArray(sriovnetworkv1.NETATTDEFFINALIZERNAME, instanceFinalizers) {
2✔
387
                instance.SetFinalizers(append(instanceFinalizers, sriovnetworkv1.NETATTDEFFINALIZERNAME))
1✔
388
                if err := r.Update(ctx, instance); err != nil {
1✔
UNCOV
389
                        return err
×
UNCOV
390
                }
×
391
        }
392

393
        return nil
1✔
394
}
395

396
func (r *genericNetworkReconciler) cleanResourcesAndFinalizers(ctx context.Context, instance NetworkCRInstance) error {
1✔
397
        instanceFinalizers := instance.GetFinalizers()
1✔
398

1✔
399
        if sriovnetworkv1.StringInArray(sriovnetworkv1.NETATTDEFFINALIZERNAME, instanceFinalizers) {
2✔
400
                // our finalizer is present, so lets handle any external dependency
1✔
401
                log.FromContext(ctx).Info("delete NetworkAttachmentDefinition CR", "Namespace", instance.NetworkNamespace(), "Name", instance.GetName())
1✔
402
                if err := r.deleteNetAttDef(ctx, instance); err != nil {
2✔
403
                        // if fail to delete the external dependency here, return with error
1✔
404
                        // so that it can be retried
1✔
405
                        return err
1✔
406
                }
1✔
407
                // remove our finalizer from the list and update it.
408
                newFinalizers, found := sriovnetworkv1.RemoveString(sriovnetworkv1.NETATTDEFFINALIZERNAME, instanceFinalizers)
1✔
409
                if found {
2✔
410
                        instance.SetFinalizers(newFinalizers)
1✔
411
                        if err := r.Update(ctx, instance); err != nil {
2✔
412
                                // If the object is not found, it's already been deleted
1✔
413
                                if errors.IsNotFound(err) {
2✔
414
                                        return nil
1✔
415
                                }
1✔
416
                                return err
1✔
417
                        }
418
                }
419
        }
420
        return nil
1✔
421
}
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