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

k8snetworkplumbingwg / sriov-network-operator / 9939865280

15 Jul 2024 01:00PM UTC coverage: 40.901% (-0.08%) from 40.981%
9939865280

push

github

web-flow
Merge pull request #734 from SchSeba/fix_mlx_plugin

Skip firmware reset on devices the operator doesn't control

16 of 53 new or added lines in 5 files covered. (30.19%)

5 existing lines in 1 file now uncovered.

5599 of 13689 relevant lines covered (40.9%)

0.45 hits per line

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

74.53
/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
        "reflect"
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/errors"
26
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27
        uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
28
        "k8s.io/apimachinery/pkg/runtime"
29
        "k8s.io/apimachinery/pkg/types"
30
        "k8s.io/client-go/util/workqueue"
31
        ctrl "sigs.k8s.io/controller-runtime"
32
        "sigs.k8s.io/controller-runtime/pkg/client"
33
        "sigs.k8s.io/controller-runtime/pkg/event"
34
        "sigs.k8s.io/controller-runtime/pkg/handler"
35
        "sigs.k8s.io/controller-runtime/pkg/log"
36
        "sigs.k8s.io/controller-runtime/pkg/reconcile"
37

38
        sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1"
39
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars"
40
)
41

42
type networkCRInstance interface {
43
        client.Object
44
        // renders NetAttDef from the network instance
45
        RenderNetAttDef() (*uns.Unstructured, error)
46
        // return name of the target namespace for the network
47
        NetworkNamespace() string
48
}
49

50
// interface which controller should implement to be compatible with genericNetworkReconciler
51
type networkController interface {
52
        reconcile.Reconciler
53
        // GetObject should return CR type which implements networkCRInstance
54
        // interface
55
        GetObject() networkCRInstance
56
        // should return CR list type
57
        GetObjectList() client.ObjectList
58
        // should return name of the controller
59
        Name() string
60
}
61

62
func newGenericNetworkReconciler(c client.Client, s *runtime.Scheme, controller networkController) *genericNetworkReconciler {
1✔
63
        return &genericNetworkReconciler{Client: c, Scheme: s, controller: controller}
1✔
64
}
1✔
65

66
// genericNetworkReconciler provide common code for all network controllers
67
type genericNetworkReconciler struct {
68
        client.Client
69
        Scheme     *runtime.Scheme
70
        controller networkController
71
}
72

73
func (r *genericNetworkReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
1✔
74
        req.Namespace = vars.Namespace
1✔
75
        reqLogger := log.FromContext(ctx).WithValues(r.controller.Name(), req.NamespacedName)
1✔
76

1✔
77
        reqLogger.Info("Reconciling " + r.controller.Name())
1✔
78
        var err error
1✔
79

1✔
80
        // Fetch instance of the network object
1✔
81
        instance := r.controller.GetObject()
1✔
82
        err = r.Get(ctx, req.NamespacedName, instance)
1✔
83
        if err != nil {
2✔
84
                if errors.IsNotFound(err) {
2✔
85
                        // Request object not found, could have been deleted after reconcile request.
1✔
86
                        // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
1✔
87
                        // Return and don't requeue
1✔
88
                        return reconcile.Result{}, nil
1✔
89
                }
1✔
90
                // Error reading the object - requeue the request.
91
                return reconcile.Result{}, err
×
92
        }
93
        instanceFinalizers := instance.GetFinalizers()
1✔
94
        // examine DeletionTimestamp to determine if object is under deletion
1✔
95
        if instance.GetDeletionTimestamp().IsZero() {
2✔
96
                // The object is not being deleted, so if it does not have our finalizer,
1✔
97
                // then lets add the finalizer and update the object. This is equivalent
1✔
98
                // registering our finalizer.
1✔
99
                if !sriovnetworkv1.StringInArray(sriovnetworkv1.NETATTDEFFINALIZERNAME, instanceFinalizers) {
2✔
100
                        instance.SetFinalizers(append(instanceFinalizers, sriovnetworkv1.NETATTDEFFINALIZERNAME))
1✔
101
                        if err := r.Update(ctx, instance); err != nil {
2✔
102
                                return reconcile.Result{}, err
1✔
103
                        }
1✔
104
                }
105
        } else {
1✔
106
                // The object is being deleted
1✔
107
                if sriovnetworkv1.StringInArray(sriovnetworkv1.NETATTDEFFINALIZERNAME, instanceFinalizers) {
2✔
108
                        // our finalizer is present, so lets handle any external dependency
1✔
109
                        reqLogger.Info("delete NetworkAttachmentDefinition CR", "Namespace", instance.NetworkNamespace(), "Name", instance.GetName())
1✔
110
                        if err := r.deleteNetAttDef(ctx, instance); err != nil {
1✔
UNCOV
111
                                // if fail to delete the external dependency here, return with error
×
UNCOV
112
                                // so that it can be retried
×
UNCOV
113
                                return reconcile.Result{}, err
×
UNCOV
114
                        }
×
115
                        // remove our finalizer from the list and update it.
116
                        newFinalizers, found := sriovnetworkv1.RemoveString(sriovnetworkv1.NETATTDEFFINALIZERNAME, instanceFinalizers)
1✔
117
                        if found {
2✔
118
                                instance.SetFinalizers(newFinalizers)
1✔
119
                                if err := r.Update(ctx, instance); err != nil {
2✔
120
                                        return reconcile.Result{}, err
1✔
121
                                }
1✔
122
                        }
123
                }
124
                return reconcile.Result{}, err
1✔
125
        }
126
        raw, err := instance.RenderNetAttDef()
1✔
127
        if err != nil {
1✔
128
                return reconcile.Result{}, err
×
129
        }
×
130
        netAttDef := &netattdefv1.NetworkAttachmentDefinition{}
1✔
131
        err = r.Scheme.Convert(raw, netAttDef, nil)
1✔
132
        if err != nil {
1✔
133
                return reconcile.Result{}, err
×
134
        }
×
135
        // format CNI config json in CR for easier readability
136
        netAttDef.Spec.Config, err = formatJSON(netAttDef.Spec.Config)
1✔
137
        if err != nil {
1✔
138
                reqLogger.Error(err, "Couldn't process rendered NetworkAttachmentDefinition config", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
×
139
                return reconcile.Result{}, err
×
140
        }
×
141
        if lnns, ok := instance.GetAnnotations()[sriovnetworkv1.LASTNETWORKNAMESPACE]; ok && netAttDef.GetNamespace() != lnns {
1✔
142
                err = r.Delete(ctx, &netattdefv1.NetworkAttachmentDefinition{
×
143
                        ObjectMeta: metav1.ObjectMeta{
×
144
                                Name:      instance.GetName(),
×
145
                                Namespace: lnns,
×
146
                        },
×
147
                })
×
148
                if err != nil {
×
149
                        reqLogger.Error(err, "Couldn't delete NetworkAttachmentDefinition CR", "Namespace", instance.GetName(), "Name", lnns)
×
150
                        return reconcile.Result{}, err
×
151
                }
×
152
        }
153
        // Check if this NetworkAttachmentDefinition already exists
154
        found := &netattdefv1.NetworkAttachmentDefinition{}
1✔
155
        err = r.Get(ctx, types.NamespacedName{Name: netAttDef.Name, Namespace: netAttDef.Namespace}, found)
1✔
156
        if err != nil {
2✔
157
                if errors.IsNotFound(err) {
2✔
158
                        targetNamespace := &corev1.Namespace{}
1✔
159
                        err = r.Get(ctx, types.NamespacedName{Name: netAttDef.Namespace}, targetNamespace)
1✔
160
                        if errors.IsNotFound(err) {
2✔
161
                                reqLogger.Info("Target namespace doesn't exist, NetworkAttachmentDefinition will be created when namespace is available", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
1✔
162
                                return reconcile.Result{}, nil
1✔
163
                        }
1✔
164

165
                        reqLogger.Info("NetworkAttachmentDefinition CR not exist, creating")
1✔
166
                        err = r.Create(ctx, netAttDef)
1✔
167
                        if err != nil {
1✔
168
                                reqLogger.Error(err, "Couldn't create NetworkAttachmentDefinition CR", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
×
169
                                return reconcile.Result{}, err
×
170
                        }
×
171
                        anno := map[string]string{sriovnetworkv1.LASTNETWORKNAMESPACE: netAttDef.Namespace}
1✔
172
                        instance.SetAnnotations(anno)
1✔
173
                        if err := r.Update(ctx, instance); err != nil {
1✔
174
                                return reconcile.Result{}, err
×
175
                        }
×
176
                } else {
×
177
                        reqLogger.Error(err, "Couldn't get NetworkAttachmentDefinition CR", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
×
178
                        return reconcile.Result{}, err
×
179
                }
×
180
        } else {
1✔
181
                reqLogger.Info("NetworkAttachmentDefinition CR already exist")
1✔
182
                if !reflect.DeepEqual(found.Spec, netAttDef.Spec) || !reflect.DeepEqual(found.GetAnnotations(), netAttDef.GetAnnotations()) {
2✔
183
                        reqLogger.Info("Update NetworkAttachmentDefinition CR", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
1✔
184
                        netAttDef.SetResourceVersion(found.GetResourceVersion())
1✔
185
                        err = r.Update(ctx, netAttDef)
1✔
186
                        if err != nil {
1✔
187
                                reqLogger.Error(err, "Couldn't update NetworkAttachmentDefinition CR", "Namespace", netAttDef.Namespace, "Name", netAttDef.Name)
×
188
                                return reconcile.Result{}, err
×
189
                        }
×
190
                }
191
        }
192

193
        return ctrl.Result{}, nil
1✔
194
}
195

196
// SetupWithManager sets up the controller with the Manager.
197
func (r *genericNetworkReconciler) SetupWithManager(mgr ctrl.Manager) error {
1✔
198
        // Reconcile when the target namespace is created after the network object.
1✔
199
        namespaceHandler := handler.Funcs{
1✔
200
                CreateFunc: r.namespaceHandlerCreate,
1✔
201
        }
1✔
202
        return ctrl.NewControllerManagedBy(mgr).
1✔
203
                For(r.controller.GetObject()).
1✔
204
                Watches(&netattdefv1.NetworkAttachmentDefinition{}, &handler.EnqueueRequestForObject{}).
1✔
205
                Watches(&corev1.Namespace{}, &namespaceHandler).
1✔
206
                Complete(r.controller)
1✔
207
}
1✔
208

209
func (r *genericNetworkReconciler) namespaceHandlerCreate(ctx context.Context, e event.CreateEvent, q workqueue.RateLimitingInterface) {
1✔
210
        networkList := r.controller.GetObjectList()
1✔
211
        err := r.List(ctx,
1✔
212
                networkList,
1✔
213
                client.MatchingFields{"spec.networkNamespace": e.Object.GetName()},
1✔
214
        )
1✔
215
        logger := log.Log.WithName(r.controller.Name() + " reconciler")
1✔
216
        if err != nil {
1✔
217
                logger.Info("Can't list networks for namespace", "resource", e.Object.GetName(), "error", err)
×
218
                return
×
219
        }
×
220
        unsContent, err := runtime.DefaultUnstructuredConverter.ToUnstructured(networkList)
1✔
221
        if err != nil {
1✔
222
                logger.Info("Can't convert network list to unstructured object", "resource", e.Object.GetName(), "error", err)
×
223
                return
×
224
        }
×
225
        unsList := &uns.Unstructured{}
1✔
226
        unsList.SetUnstructuredContent(unsContent)
1✔
227
        _ = unsList.EachListItem(func(o runtime.Object) error {
2✔
228
                unsObj := o.(*uns.Unstructured)
1✔
229
                q.Add(reconcile.Request{NamespacedName: types.NamespacedName{
1✔
230
                        Namespace: unsObj.GetNamespace(),
1✔
231
                        Name:      unsObj.GetName(),
1✔
232
                }})
1✔
233
                return nil
1✔
234
        })
1✔
235
}
236

237
// deleteNetAttDef deletes the generated net-att-def CR
238
func (r *genericNetworkReconciler) deleteNetAttDef(ctx context.Context, cr networkCRInstance) error {
1✔
239
        // Fetch the NetworkAttachmentDefinition instance
1✔
240
        namespace := cr.NetworkNamespace()
1✔
241
        if namespace == "" {
2✔
242
                namespace = cr.GetNamespace()
1✔
243
        }
1✔
244
        instance := &netattdefv1.NetworkAttachmentDefinition{ObjectMeta: metav1.ObjectMeta{Name: cr.GetName(), Namespace: namespace}}
1✔
245
        err := r.Delete(ctx, instance)
1✔
246
        if err != nil {
2✔
247
                if errors.IsNotFound(err) {
2✔
248
                        return nil
1✔
249
                }
1✔
UNCOV
250
                return err
×
251
        }
252
        return nil
1✔
253
}
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

© 2025 Coveralls, Inc