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

k8snetworkplumbingwg / sriov-network-operator / 19227470377

10 Nov 2025 09:48AM UTC coverage: 62.151% (-0.2%) from 62.366%
19227470377

Pull #902

github

web-flow
Merge f9637c189 into 3d1a472a6
Pull Request #902: Create platform and orchestrator packages

319 of 659 new or added lines in 25 files covered. (48.41%)

41 existing lines in 9 files now uncovered.

8772 of 14114 relevant lines covered (62.15%)

0.69 hits per line

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

73.16
/controllers/sriovoperatorconfig_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
        "errors"
22
        "fmt"
23
        "os"
24
        "sort"
25
        "strings"
26

27
        appsv1 "k8s.io/api/apps/v1"
28
        corev1 "k8s.io/api/core/v1"
29
        apierrors "k8s.io/apimachinery/pkg/api/errors"
30
        uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
31
        "k8s.io/apimachinery/pkg/runtime"
32
        "k8s.io/apimachinery/pkg/runtime/schema"
33
        "k8s.io/apimachinery/pkg/types"
34
        kscheme "k8s.io/client-go/kubernetes/scheme"
35
        ctrl "sigs.k8s.io/controller-runtime"
36
        ctrl_builder "sigs.k8s.io/controller-runtime/pkg/builder"
37
        "sigs.k8s.io/controller-runtime/pkg/client"
38
        "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
39
        "sigs.k8s.io/controller-runtime/pkg/log"
40
        "sigs.k8s.io/controller-runtime/pkg/predicate"
41
        "sigs.k8s.io/controller-runtime/pkg/reconcile"
42

43
        "github.com/go-logr/logr"
44
        machinev1 "github.com/openshift/api/machineconfiguration/v1"
45

46
        sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1"
47
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/apply"
48
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts"
49
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/featuregate"
50
        snolog "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/log"
51
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/orchestrator"
52
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/render"
53
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars"
54
)
55

56
// SriovOperatorConfigReconciler reconciles a SriovOperatorConfig object
57
type SriovOperatorConfigReconciler struct {
58
        client.Client
59
        Scheme            *runtime.Scheme
60
        Orchestrator      orchestrator.Interface
61
        FeatureGate       featuregate.FeatureGate
62
        UncachedAPIReader client.Reader
63
}
64

65
//+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovoperatorconfigs,verbs=get;list;watch;create;update;patch;delete
66
//+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovoperatorconfigs/status,verbs=get;update;patch
67
//+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovoperatorconfigs/finalizers,verbs=update
68

69
// Reconcile is part of the main kubernetes reconciliation loop which aims to
70
// move the current state of the cluster closer to the desired state.
71
// TODO(user): Modify the Reconcile function to compare the state specified by
72
// the SriovOperatorConfig object against the actual cluster state, and then
73
// perform operations to make the cluster state reflect the state specified by
74
// the user.
75
//
76
// For more details, check Reconcile and its Result here:
77
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.8.3/pkg/reconcile
78
func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
1✔
79
        logger := log.FromContext(ctx).WithValues("sriovoperatorconfig", req.NamespacedName)
1✔
80
        logger.Info("Reconciling SriovOperatorConfig")
1✔
81

1✔
82
        // Note: in SetupWithManager we setup manager to enqueue only default config obj
1✔
83
        defaultConfig := &sriovnetworkv1.SriovOperatorConfig{}
1✔
84
        err := r.Get(ctx, req.NamespacedName, defaultConfig)
1✔
85
        if err != nil {
2✔
86
                if apierrors.IsNotFound(err) {
2✔
87
                        logger.Info("default SriovOperatorConfig object not found. waiting for creation.")
1✔
88
                        return reconcile.Result{}, nil
1✔
89
                }
1✔
90
                // Error reading the object - requeue the request.
91
                logger.Error(err, "Failed to get default SriovOperatorConfig object")
×
92
                return reconcile.Result{}, err
×
93
        }
94

95
        snolog.SetLogLevel(defaultConfig.Spec.LogLevel)
1✔
96

1✔
97
        // examine DeletionTimestamp to determine if object is under deletion
1✔
98
        if !defaultConfig.ObjectMeta.DeletionTimestamp.IsZero() {
2✔
99
                // The object is being deleted
1✔
100
                return r.handleSriovOperatorConfigDeletion(ctx, defaultConfig, logger)
1✔
101
        }
1✔
102

103
        if err = r.syncOperatorConfigFinalizers(ctx, defaultConfig, logger); err != nil {
1✔
104
                return reconcile.Result{}, err
×
105
        }
×
106

107
        r.FeatureGate.Init(defaultConfig.Spec.FeatureGates)
1✔
108
        logger.Info("enabled featureGates", "featureGates", r.FeatureGate.String())
1✔
109

1✔
110
        if !defaultConfig.Spec.EnableInjector {
2✔
111
                logger.Info("SR-IOV Network Resource Injector is disabled.")
1✔
112
        }
1✔
113

114
        if !defaultConfig.Spec.EnableOperatorWebhook {
2✔
115
                logger.Info("SR-IOV Network Operator Webhook is disabled.")
1✔
116
        }
1✔
117

118
        // Fetch the SriovNetworkNodePolicyList
119
        policyList := &sriovnetworkv1.SriovNetworkNodePolicyList{}
1✔
120
        err = r.List(ctx, policyList, &client.ListOptions{})
1✔
121
        if err != nil {
1✔
122
                // Error reading the object - requeue the request.
×
123
                return reconcile.Result{}, err
×
124
        }
×
125
        // Sort the policies with priority, higher priority ones is applied later
126
        // We need to use the sort so we always get the policies in the same order
127
        // That is needed so when we create the node Affinity for the sriov-device plugin
128
        // it will remain in the same order and not trigger a pod recreation
129
        sort.Sort(sriovnetworkv1.ByPriority(policyList.Items))
1✔
130

1✔
131
        // Render and sync webhook objects
1✔
132
        if err = r.syncWebhookObjs(ctx, defaultConfig); err != nil {
2✔
133
                return reconcile.Result{}, err
1✔
134
        }
1✔
135

136
        // Sync SriovNetworkConfigDaemon objects
137
        if err = r.syncConfigDaemonSet(ctx, defaultConfig); err != nil {
1✔
138
                return reconcile.Result{}, err
×
139
        }
×
140

141
        if err = syncPluginDaemonObjs(ctx, r.Client, r.Scheme, defaultConfig); err != nil {
1✔
142
                return reconcile.Result{}, err
×
143
        }
×
144

145
        if err = r.syncMetricsExporter(ctx, defaultConfig); err != nil {
1✔
146
                return reconcile.Result{}, err
×
147
        }
×
148

149
        // For Openshift we need to create the systemd files using a machine config
150
        if r.Orchestrator.ClusterType() == consts.ClusterTypeOpenshift {
2✔
151
                // TODO: add support for hypershift as today there is no MCO on hypershift clusters
1✔
152
                if r.Orchestrator.Flavor() == consts.ClusterFlavorHypershift {
1✔
153
                        return ctrl.Result{}, fmt.Errorf("systemd mode is not supported on hypershift")
×
154
                }
×
155

156
                if err = r.syncOpenShiftSystemdService(ctx, defaultConfig); err != nil {
1✔
157
                        return reconcile.Result{}, err
×
158
                }
×
159
        }
160

161
        logger.Info("Reconcile SriovOperatorConfig completed successfully")
1✔
162
        return reconcile.Result{RequeueAfter: consts.ResyncPeriod}, nil
1✔
163
}
164

165
// defaultConfigPredicate creates a predicate.Predicate that will return true
166
// only for the default sriovoperatorconfig obj.
167
func defaultConfigPredicate() predicate.Predicate {
1✔
168
        return predicate.NewPredicateFuncs(func(object client.Object) bool {
2✔
169
                if object.GetName() == consts.DefaultConfigName && object.GetNamespace() == vars.Namespace {
2✔
170
                        return true
1✔
171
                }
1✔
172
                return false
×
173
        })
174
}
175

176
// SetupWithManager sets up the controller with the Manager.
177
func (r *SriovOperatorConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
1✔
178
        return ctrl.NewControllerManagedBy(mgr).
1✔
179
                For(&sriovnetworkv1.SriovOperatorConfig{}, ctrl_builder.WithPredicates(defaultConfigPredicate())).
1✔
180
                Owns(&appsv1.DaemonSet{}).
1✔
181
                Owns(&corev1.ConfigMap{}).
1✔
182
                Complete(r)
1✔
183
}
1✔
184

185
func (r *SriovOperatorConfigReconciler) syncConfigDaemonSet(ctx context.Context, dc *sriovnetworkv1.SriovOperatorConfig) error {
1✔
186
        logger := log.Log.WithName("syncConfigDaemonset")
1✔
187
        logger.V(1).Info("Start to sync config daemonset")
1✔
188

1✔
189
        data := render.MakeRenderData()
1✔
190
        data.Data["Image"] = os.Getenv("SRIOV_NETWORK_CONFIG_DAEMON_IMAGE")
1✔
191
        data.Data["Namespace"] = vars.Namespace
1✔
192
        data.Data["SRIOVCNIImage"] = os.Getenv("SRIOV_CNI_IMAGE")
1✔
193
        data.Data["SRIOVInfiniBandCNIImage"] = os.Getenv("SRIOV_INFINIBAND_CNI_IMAGE")
1✔
194
        data.Data["OVSCNIImage"] = os.Getenv("OVS_CNI_IMAGE")
1✔
195
        data.Data["RDMACNIImage"] = os.Getenv("RDMA_CNI_IMAGE")
1✔
196
        data.Data["ReleaseVersion"] = os.Getenv("RELEASEVERSION")
1✔
197
        data.Data["ClusterType"] = vars.ClusterType
1✔
198
        data.Data["DevMode"] = os.Getenv("DEV_MODE")
1✔
199
        data.Data["ImagePullSecrets"] = GetImagePullSecrets()
1✔
200
        if dc.Spec.ConfigurationMode == sriovnetworkv1.SystemdConfigurationMode {
1✔
201
                data.Data["UsedSystemdMode"] = true
×
202
        } else {
1✔
203
                data.Data["UsedSystemdMode"] = false
1✔
204
        }
1✔
205
        data.Data["ParallelNicConfig"] = r.FeatureGate.IsEnabled(consts.ParallelNicConfigFeatureGate)
1✔
206
        data.Data["ManageSoftwareBridges"] = r.FeatureGate.IsEnabled(consts.ManageSoftwareBridgesFeatureGate)
1✔
207

1✔
208
        envCniBinPath := os.Getenv("SRIOV_CNI_BIN_PATH")
1✔
209
        if envCniBinPath == "" {
2✔
210
                data.Data["CNIBinPath"] = "/var/lib/cni/bin"
1✔
211
        } else {
1✔
212
                logger.V(1).Info("New cni bin found", "CNIBinPath", envCniBinPath)
×
213
                data.Data["CNIBinPath"] = envCniBinPath
×
214
        }
×
215

216
        if len(dc.Spec.DisablePlugins) > 0 {
2✔
217
                logger.V(1).Info("DisablePlugins provided", "DisablePlugins", dc.Spec.DisablePlugins)
1✔
218
                data.Data["DisablePlugins"] = strings.Join(dc.Spec.DisablePlugins.ToStringSlice(), ",")
1✔
219
        }
1✔
220

221
        objs, err := render.RenderDir(consts.ConfigDaemonPath, &data)
1✔
222
        if err != nil {
1✔
223
                logger.Error(err, "Fail to render config daemon manifests")
×
224
                return err
×
225
        }
×
226
        // Sync DaemonSets
227
        for _, obj := range objs {
2✔
228
                if obj.GetKind() == "DaemonSet" {
2✔
229
                        err = updateDaemonsetNodeSelector(obj, dc.Spec.ConfigDaemonNodeSelector)
1✔
230
                        if err != nil {
1✔
231
                                return err
×
232
                        }
×
233
                }
234

235
                err = r.syncK8sResource(ctx, dc, obj)
1✔
236
                if err != nil {
1✔
237
                        logger.Error(err, "Couldn't sync SR-IOV daemons objects")
×
238
                        return err
×
239
                }
×
240
        }
241
        return nil
1✔
242
}
243

244
func (r *SriovOperatorConfigReconciler) syncMetricsExporter(ctx context.Context, dc *sriovnetworkv1.SriovOperatorConfig) error {
1✔
245
        logger := log.Log.WithName("syncMetricsExporter")
1✔
246
        logger.V(1).Info("Start to sync metrics exporter")
1✔
247

1✔
248
        data := render.MakeRenderData()
1✔
249
        data.Data["Image"] = os.Getenv("METRICS_EXPORTER_IMAGE")
1✔
250
        data.Data["Namespace"] = vars.Namespace
1✔
251
        data.Data["ImagePullSecrets"] = GetImagePullSecrets()
1✔
252
        data.Data["MetricsExporterSecretName"] = os.Getenv("METRICS_EXPORTER_SECRET_NAME")
1✔
253
        data.Data["MetricsExporterPort"] = os.Getenv("METRICS_EXPORTER_PORT")
1✔
254
        data.Data["MetricsExporterKubeRbacProxyImage"] = os.Getenv("METRICS_EXPORTER_KUBE_RBAC_PROXY_IMAGE")
1✔
255

1✔
256
        data.Data["IsOpenshift"] = r.Orchestrator.ClusterType() == consts.ClusterTypeOpenshift
1✔
257

1✔
258
        data.Data["IsPrometheusOperatorInstalled"] = strings.ToLower(os.Getenv("METRICS_EXPORTER_PROMETHEUS_OPERATOR_ENABLED")) == trueString
1✔
259
        data.Data["PrometheusOperatorDeployRules"] = strings.ToLower(os.Getenv("METRICS_EXPORTER_PROMETHEUS_DEPLOY_RULES")) == trueString
1✔
260
        data.Data["PrometheusOperatorServiceAccount"] = os.Getenv("METRICS_EXPORTER_PROMETHEUS_OPERATOR_SERVICE_ACCOUNT")
1✔
261
        data.Data["PrometheusOperatorNamespace"] = os.Getenv("METRICS_EXPORTER_PROMETHEUS_OPERATOR_NAMESPACE")
1✔
262

1✔
263
        data.Data["NodeSelectorField"] = GetDefaultNodeSelector()
1✔
264
        if dc.Spec.ConfigDaemonNodeSelector != nil {
2✔
265
                data.Data["NodeSelectorField"] = dc.Spec.ConfigDaemonNodeSelector
1✔
266
        }
1✔
267

268
        objs, err := render.RenderDir(consts.MetricsExporterPath, &data)
1✔
269
        if err != nil {
1✔
270
                logger.Error(err, "Fail to render metrics exporter manifests")
×
271
                return err
×
272
        }
×
273

274
        if r.FeatureGate.IsEnabled(consts.MetricsExporterFeatureGate) {
2✔
275
                for _, obj := range objs {
2✔
276
                        err = r.syncK8sResource(ctx, dc, obj)
1✔
277
                        if err != nil {
1✔
278
                                logger.Error(err, "Couldn't sync metrics exporter objects")
×
279
                                return err
×
280
                        }
×
281
                }
282

283
                return nil
1✔
284
        }
285

286
        err = r.deleteK8sResources(ctx, objs)
1✔
287
        if err != nil {
1✔
288
                return err
×
289
        }
×
290

291
        return nil
1✔
292
}
293

294
func (r *SriovOperatorConfigReconciler) syncWebhookObjs(ctx context.Context, dc *sriovnetworkv1.SriovOperatorConfig) error {
1✔
295
        logger := log.Log.WithName("syncWebhookObjs")
1✔
296
        logger.V(1).Info("Start to sync webhook objects")
1✔
297

1✔
298
        for name, path := range webhooks {
2✔
299
                // Render Webhook manifests
1✔
300
                data := render.MakeRenderData()
1✔
301
                data.Data["Namespace"] = vars.Namespace
1✔
302
                data.Data["SRIOVMutatingWebhookName"] = name
1✔
303
                data.Data["NetworkResourcesInjectorImage"] = os.Getenv("NETWORK_RESOURCES_INJECTOR_IMAGE")
1✔
304
                data.Data["SriovNetworkWebhookImage"] = os.Getenv("SRIOV_NETWORK_WEBHOOK_IMAGE")
1✔
305
                data.Data["ReleaseVersion"] = os.Getenv("RELEASEVERSION")
1✔
306
                data.Data["ClusterType"] = vars.ClusterType
1✔
307
                data.Data["DevMode"] = os.Getenv("DEV_MODE")
1✔
308
                data.Data["ImagePullSecrets"] = GetImagePullSecrets()
1✔
309
                data.Data["CertManagerEnabled"] = strings.ToLower(os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_CERT_MANAGER_ENABLED")) == trueString
1✔
310
                data.Data["OperatorWebhookSecretName"] = os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_OPERATOR_SECRET_NAME")
1✔
311
                data.Data["OperatorWebhookCA"] = os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_OPERATOR_CA_CRT")
1✔
312
                data.Data["InjectorWebhookSecretName"] = os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_INJECTOR_SECRET_NAME")
1✔
313
                data.Data["InjectorWebhookCA"] = os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_INJECTOR_CA_CRT")
1✔
314

1✔
315
                operatorWebhookPort := os.Getenv("OPERATOR_WEBHOOK_NETWORK_POLICY_PORT")
1✔
316
                if operatorWebhookPort == "" {
2✔
317
                        operatorWebhookPort = "6443"
1✔
318
                }
1✔
319
                data.Data["OperatorWebhookNetworkPolicyPort"] = operatorWebhookPort
1✔
320

1✔
321
                injectorWebhookPort := os.Getenv("INJECTOR_WEBHOOK_NETWORK_POLICY_PORT")
1✔
322
                if injectorWebhookPort == "" {
2✔
323
                        injectorWebhookPort = "6443"
1✔
324
                }
1✔
325
                data.Data["InjectorWebhookNetworkPolicyPort"] = injectorWebhookPort
1✔
326

1✔
327
                data.Data["ExternalControlPlane"] = false
1✔
328
                if r.Orchestrator.ClusterType() == consts.ClusterTypeOpenshift &&
1✔
329
                        r.Orchestrator.Flavor() == consts.ClusterFlavorHypershift {
1✔
NEW
330
                        data.Data["ExternalControlPlane"] = true
×
UNCOV
331
                }
×
332

333
                // check for ResourceInjectorMatchConditionFeatureGate feature gate
334
                data.Data[consts.ResourceInjectorMatchConditionFeatureGate] = r.FeatureGate.IsEnabled(consts.ResourceInjectorMatchConditionFeatureGate)
1✔
335

1✔
336
                objs, err := render.RenderDir(path, &data)
1✔
337
                if err != nil {
1✔
338
                        logger.Error(err, "Fail to render webhook manifests")
×
339
                        return err
×
340
                }
×
341

342
                // Delete injector webhook
343
                if !dc.Spec.EnableInjector && path == consts.InjectorWebHookPath {
2✔
344
                        for _, obj := range objs {
2✔
345
                                err = r.deleteWebhookObject(ctx, obj)
1✔
346
                                if err != nil {
1✔
347
                                        return err
×
348
                                }
×
349
                        }
350
                        logger.Info("SR-IOV Admission Controller is disabled.")
1✔
351
                        logger.Info("To enable SR-IOV Admission Controller,")
1✔
352
                        logger.Info("Set 'SriovOperatorConfig.Spec.EnableInjector' to true(bool).")
1✔
353
                        continue
1✔
354
                }
355
                // Delete operator webhook
356
                if !dc.Spec.EnableOperatorWebhook && path == consts.OperatorWebHookPath {
2✔
357
                        for _, obj := range objs {
2✔
358
                                err = r.deleteWebhookObject(ctx, obj)
1✔
359
                                if err != nil {
1✔
360
                                        return err
×
361
                                }
×
362
                        }
363
                        logger.Info("Operator Admission Controller is disabled.")
1✔
364
                        logger.Info("To enable Operator Admission Controller,")
1✔
365
                        logger.Info("Set 'SriovOperatorConfig.Spec.EnableOperatorWebhook' to true(bool).")
1✔
366
                        continue
1✔
367
                }
368

369
                // Sync Webhook
370
                for _, obj := range objs {
2✔
371
                        err = r.syncK8sResource(ctx, dc, obj)
1✔
372
                        if err != nil {
2✔
373
                                logger.Error(err, "Couldn't sync webhook objects")
1✔
374
                                return err
1✔
375
                        }
1✔
376
                }
377
        }
378

379
        return nil
1✔
380
}
381

382
func (r *SriovOperatorConfigReconciler) deleteWebhookObject(ctx context.Context, obj *uns.Unstructured) error {
1✔
383
        if err := r.deleteK8sResource(ctx, obj); err != nil {
1✔
384
                return err
×
385
        }
×
386
        return nil
1✔
387
}
388

389
func (r *SriovOperatorConfigReconciler) deleteK8sResource(ctx context.Context, in *uns.Unstructured) error {
1✔
390
        if err := apply.DeleteObject(ctx, r.Client, in); err != nil {
1✔
391
                return fmt.Errorf("failed to delete object %v with err: %v", in, err)
×
392
        }
×
393
        return nil
1✔
394
}
395

396
func (r *SriovOperatorConfigReconciler) deleteK8sResources(ctx context.Context, objs []*uns.Unstructured) error {
1✔
397
        for _, obj := range objs {
2✔
398
                err := r.deleteK8sResource(ctx, obj)
1✔
399
                if err != nil {
1✔
400
                        return err
×
401
                }
×
402
        }
403
        return nil
1✔
404
}
405

406
func (r *SriovOperatorConfigReconciler) syncK8sResource(ctx context.Context, cr *sriovnetworkv1.SriovOperatorConfig, in *uns.Unstructured) error {
1✔
407
        switch in.GetKind() {
1✔
408
        case clusterRoleResourceName, clusterRoleBindingResourceName, mutatingWebhookConfigurationCRDName, validatingWebhookConfigurationCRDName, machineConfigCRDName:
1✔
409
        default:
1✔
410
                // set owner-reference only for namespaced objects
1✔
411
                if err := controllerutil.SetControllerReference(cr, in, r.Scheme); err != nil {
1✔
412
                        return err
×
413
                }
×
414
        }
415
        if err := apply.ApplyObject(ctx, r.Client, in); err != nil {
2✔
416
                return fmt.Errorf("failed to apply object %v with err: %v", in, err)
1✔
417
        }
1✔
418
        return nil
1✔
419
}
420

421
// syncOpenShiftSystemdService creates the Machine Config to deploy the systemd service on openshift ONLY
422
func (r *SriovOperatorConfigReconciler) syncOpenShiftSystemdService(ctx context.Context, cr *sriovnetworkv1.SriovOperatorConfig) error {
1✔
423
        logger := log.Log.WithName("syncSystemdService")
1✔
424

1✔
425
        if cr.Spec.ConfigurationMode != sriovnetworkv1.SystemdConfigurationMode {
2✔
426
                obj := &machinev1.MachineConfig{}
1✔
427
                // use uncached api reader to get machineconfig to reduce memory footprint
1✔
428
                err := r.UncachedAPIReader.Get(ctx, types.NamespacedName{Name: consts.SystemdServiceOcpMachineConfigName}, obj)
1✔
429
                if err != nil {
2✔
430
                        if apierrors.IsNotFound(err) {
2✔
431
                                return nil
1✔
432
                        }
1✔
433

434
                        logger.Error(err, "failed to get machine config for the sriov-systemd-service")
×
435
                        return err
×
436
                }
437

438
                logger.Info("Systemd service was deployed but the operator is now operating on daemonset mode, removing the machine config")
×
439
                err = r.Delete(ctx, obj)
×
440
                if err != nil {
×
441
                        logger.Error(err, "failed to remove the systemd service machine config")
×
442
                        return err
×
443
                }
×
444

445
                return nil
×
446
        }
447

448
        logger.Info("Start to sync config systemd machine config for openshift")
×
449
        data := render.MakeRenderData()
×
450
        data.Data["LogLevel"] = cr.Spec.LogLevel
×
451
        objs, err := render.RenderDir(consts.SystemdServiceOcpPath, &data)
×
452
        if err != nil {
×
453
                logger.Error(err, "Fail to render config daemon manifests")
×
454
                return err
×
455
        }
×
456

457
        // Sync machine config
458
        return r.setLabelInsideObject(ctx, cr, objs)
×
459
}
460

461
func (r SriovOperatorConfigReconciler) syncOperatorConfigFinalizers(ctx context.Context, defaultConfig *sriovnetworkv1.SriovOperatorConfig, logger logr.Logger) error {
1✔
462
        if sriovnetworkv1.StringInArray(sriovnetworkv1.OPERATORCONFIGFINALIZERNAME, defaultConfig.ObjectMeta.Finalizers) {
2✔
463
                return nil
1✔
464
        }
1✔
465

466
        newObj := defaultConfig.DeepCopyObject().(client.Object)
1✔
467
        newObj.SetFinalizers(
1✔
468
                append(newObj.GetFinalizers(), sriovnetworkv1.OPERATORCONFIGFINALIZERNAME),
1✔
469
        )
1✔
470

1✔
471
        logger.WithName("syncOperatorConfigFinalizers").
1✔
472
                Info("Adding finalizer", "key", sriovnetworkv1.OPERATORCONFIGFINALIZERNAME)
1✔
473

1✔
474
        patch := client.MergeFrom(defaultConfig)
1✔
475
        err := r.Patch(ctx, newObj, patch)
1✔
476
        if err != nil {
1✔
477
                return fmt.Errorf("can't patch SriovOperatorConfig to add finalizer [%s]: %w", sriovnetworkv1.OPERATORCONFIGFINALIZERNAME, err)
×
478
        }
×
479

480
        // Refresh the defaultConfig object with the latest changes
481
        return r.Get(ctx, types.NamespacedName{Namespace: defaultConfig.Namespace, Name: defaultConfig.Name}, defaultConfig)
1✔
482
}
483

484
func (r *SriovOperatorConfigReconciler) handleSriovOperatorConfigDeletion(ctx context.Context,
485
        defaultConfig *sriovnetworkv1.SriovOperatorConfig, logger logr.Logger) (ctrl.Result, error) {
1✔
486
        var err error
1✔
487
        if sriovnetworkv1.StringInArray(sriovnetworkv1.OPERATORCONFIGFINALIZERNAME, defaultConfig.ObjectMeta.Finalizers) {
2✔
488
                // our finalizer is present, so lets handle any external dependency
1✔
489
                logger.Info("delete SriovOperatorConfig CR", "Namespace", defaultConfig.Namespace, "Name", defaultConfig.Name)
1✔
490
                // make sure webhooks objects are deleted prior of removing finalizer
1✔
491
                err = r.deleteAllWebhooks(ctx)
1✔
492
                if err != nil {
1✔
493
                        return reconcile.Result{}, err
×
494
                }
×
495
                // remove our finalizer from the list and update it.
496
                defaultConfig.ObjectMeta.Finalizers, _ = sriovnetworkv1.RemoveString(sriovnetworkv1.OPERATORCONFIGFINALIZERNAME, defaultConfig.ObjectMeta.Finalizers)
1✔
497
                if err := r.Update(ctx, defaultConfig); err != nil {
1✔
498
                        return reconcile.Result{}, err
×
499
                }
×
500
        }
501

502
        return reconcile.Result{}, err
1✔
503
}
504

505
func (r SriovOperatorConfigReconciler) setLabelInsideObject(ctx context.Context, cr *sriovnetworkv1.SriovOperatorConfig, objs []*uns.Unstructured) error {
×
506
        logger := log.Log.WithName("setLabelInsideObject")
×
507
        for _, obj := range objs {
×
508
                if obj.GetKind() == machineConfigCRDName && len(cr.Spec.ConfigDaemonNodeSelector) > 0 {
×
509
                        scheme := kscheme.Scheme
×
510
                        mc := &machinev1.ControllerConfig{}
×
511
                        err := scheme.Convert(obj, mc, nil)
×
512
                        if err != nil {
×
513
                                logger.Error(err, "Fail to convert to MachineConfig")
×
514
                                return err
×
515
                        }
×
516
                        mc.Labels = cr.Spec.ConfigDaemonNodeSelector
×
517
                        err = scheme.Convert(mc, obj, nil)
×
518
                        if err != nil {
×
519
                                logger.Error(err, "Fail to convert to Unstructured")
×
520
                                return err
×
521
                        }
×
522
                }
523
                err := r.syncK8sResource(ctx, cr, obj)
×
524
                if err != nil {
×
525
                        logger.Error(err, "Couldn't sync SR-IOV daemons objects")
×
526
                        return err
×
527
                }
×
528
        }
529

530
        return nil
×
531
}
532

533
func (r SriovOperatorConfigReconciler) deleteAllWebhooks(ctx context.Context) error {
1✔
534
        var err error
1✔
535
        obj := &uns.Unstructured{}
1✔
536
        obj.SetGroupVersionKind(schema.GroupVersionKind{Group: "admissionregistration.k8s.io", Kind: "MutatingWebhookConfiguration", Version: "v1"})
1✔
537
        obj.SetName(consts.OperatorWebHookName)
1✔
538
        err = errors.Join(
1✔
539
                err, r.deleteWebhookObject(ctx, obj),
1✔
540
        )
1✔
541

1✔
542
        obj = &uns.Unstructured{}
1✔
543
        obj.SetGroupVersionKind(schema.GroupVersionKind{Group: "admissionregistration.k8s.io", Kind: "ValidatingWebhookConfiguration", Version: "v1"})
1✔
544
        obj.SetName(consts.OperatorWebHookName)
1✔
545
        err = errors.Join(
1✔
546
                err, r.deleteWebhookObject(ctx, obj),
1✔
547
        )
1✔
548

1✔
549
        obj = &uns.Unstructured{}
1✔
550
        obj.SetGroupVersionKind(schema.GroupVersionKind{Group: "admissionregistration.k8s.io", Kind: "MutatingWebhookConfiguration", Version: "v1"})
1✔
551
        obj.SetName(consts.InjectorWebHookName)
1✔
552
        err = errors.Join(
1✔
553
                err, r.deleteWebhookObject(ctx, obj),
1✔
554
        )
1✔
555

1✔
556
        return err
1✔
557
}
1✔
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