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

k8snetworkplumbingwg / sriov-network-operator / 3924301767

pending completion
3924301767

Pull #395

github

GitHub
Merge ae949cc0e into 8f5bcbb8d
Pull Request #395: Use ginkgo/v2 CLI --junit-report flag

1899 of 7509 relevant lines covered (25.29%)

0.29 hits per line

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

54.89
/controllers/sriovnetworkpoolconfig_controller.go
1
package controllers
2

3
import (
4
        "context"
5
        "encoding/json"
6
        "fmt"
7
        "reflect"
8

9
        "k8s.io/apimachinery/pkg/api/errors"
10
        "k8s.io/apimachinery/pkg/runtime"
11
        "k8s.io/apimachinery/pkg/types"
12
        ctrl "sigs.k8s.io/controller-runtime"
13
        "sigs.k8s.io/controller-runtime/pkg/client"
14
        "sigs.k8s.io/controller-runtime/pkg/log"
15
        "sigs.k8s.io/controller-runtime/pkg/reconcile"
16

17
        sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1"
18
        constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts"
19
        render "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/render"
20
        utils "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils"
21
        mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1"
22
)
23

24
// SriovNetworkPoolConfigReconciler reconciles a SriovNetworkPoolConfig object
25
type SriovNetworkPoolConfigReconciler struct {
26
        client.Client
27
        Scheme *runtime.Scheme
28
}
29

30
//+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovnetworkpoolconfigs,verbs=get;list;watch;create;update;patch;delete
31
//+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovnetworkpoolconfigs/status,verbs=get;update;patch
32
//+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovnetworkpoolconfigs/finalizers,verbs=update
33

34
// Reconcile is part of the main kubernetes reconciliation loop which aims to
35
// move the current state of the cluster closer to the desired state.
36
// TODO(user): Modify the Reconcile function to compare the state specified by
37
// the SriovNetworkPoolConfig object against the actual cluster state, and then
38
// perform operations to make the cluster state reflect the state specified by
39
// the user.
40
//
41
// For more details, check Reconcile and its Result here:
42
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.6.4/pkg/reconcile
43
func (r *SriovNetworkPoolConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
1✔
44
        logger := log.FromContext(ctx).WithValues("sriovnetworkpoolconfig", req.NamespacedName)
1✔
45
        isHypershift := false
1✔
46
        if utils.ClusterType == utils.ClusterTypeOpenshift {
2✔
47
                var err error
1✔
48
                if isHypershift, err = utils.IsExternalControlPlaneCluster(r.Client); err != nil {
1✔
49
                        return reconcile.Result{}, err
×
50
                }
×
51
                logger = logger.WithValues("isHypershift", isHypershift)
1✔
52
        }
53
        logger.Info("Reconciling")
1✔
54

1✔
55
        // // Fetch SriovNetworkPoolConfig
1✔
56
        instance := &sriovnetworkv1.SriovNetworkPoolConfig{}
1✔
57
        err := r.Get(ctx, req.NamespacedName, instance)
1✔
58
        if err != nil {
1✔
59
                if errors.IsNotFound(err) {
×
60
                        // Request object not found, could have been deleted after reconcile request.
×
61
                        // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
×
62
                        // Return and don't requeue
×
63
                        logger.Info("instance not found")
×
64
                        return reconcile.Result{}, nil
×
65
                }
×
66
                // Error reading the object - requeue the request.
67
                return reconcile.Result{}, err
×
68
        }
69

70
        // examine DeletionTimestamp to determine if object is under deletion
71
        if instance.ObjectMeta.DeletionTimestamp.IsZero() {
2✔
72
                // The object is not being deleted, so if it does not have our finalizer,
1✔
73
                // then lets add the finalizer and update the object. This is equivalent
1✔
74
                // registering our finalizer.
1✔
75
                if !sriovnetworkv1.StringInArray(sriovnetworkv1.POOLCONFIGFINALIZERNAME, instance.ObjectMeta.Finalizers) {
2✔
76
                        instance.ObjectMeta.Finalizers = append(instance.ObjectMeta.Finalizers, sriovnetworkv1.POOLCONFIGFINALIZERNAME)
1✔
77
                        if err := r.Update(ctx, instance); err != nil {
1✔
78
                                return reconcile.Result{}, err
×
79
                        }
×
80
                }
81
                if utils.ClusterType == utils.ClusterTypeOpenshift {
2✔
82
                        if !isHypershift {
2✔
83
                                if err = r.syncOvsHardwareOffloadMachineConfigs(ctx, instance, false); err != nil {
1✔
84
                                        return reconcile.Result{}, err
×
85
                                }
×
86
                        } else {
×
87
                                logger.Info("Ignoring request to enable HWOL (running on Hypershift)")
×
88
                        }
×
89
                }
90
        } else {
×
91
                // The object is being deleted
×
92
                if sriovnetworkv1.StringInArray(sriovnetworkv1.POOLCONFIGFINALIZERNAME, instance.ObjectMeta.Finalizers) {
×
93
                        // our finalizer is present, so lets handle any external dependency
×
94
                        logger.Info("delete SriovNetworkPoolConfig CR", "Namespace", instance.Namespace, "Name", instance.Name)
×
95
                        if utils.ClusterType == utils.ClusterTypeOpenshift && !isHypershift {
×
96
                                if err = r.syncOvsHardwareOffloadMachineConfigs(ctx, instance, true); err != nil {
×
97
                                        // if fail to delete the external dependency here, return with error
×
98
                                        // so that it can be retried
×
99
                                        return reconcile.Result{}, err
×
100
                                }
×
101
                        }
102
                        // remove our finalizer from the list and update it.
103
                        var found bool
×
104
                        instance.ObjectMeta.Finalizers, found = sriovnetworkv1.RemoveString(sriovnetworkv1.POOLCONFIGFINALIZERNAME, instance.ObjectMeta.Finalizers)
×
105
                        if found {
×
106
                                if err := r.Update(ctx, instance); err != nil {
×
107
                                        return reconcile.Result{}, err
×
108
                                }
×
109
                        }
110
                }
111
                return reconcile.Result{}, err
×
112
        }
113

114
        return reconcile.Result{RequeueAfter: constants.ResyncPeriod}, nil
1✔
115
}
116

117
// SetupWithManager sets up the controller with the Manager.
118
func (r *SriovNetworkPoolConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
1✔
119
        return ctrl.NewControllerManagedBy(mgr).
1✔
120
                For(&sriovnetworkv1.SriovNetworkPoolConfig{}).
1✔
121
                Complete(r)
1✔
122
}
1✔
123

124
func (r *SriovNetworkPoolConfigReconciler) syncOvsHardwareOffloadMachineConfigs(ctx context.Context, nc *sriovnetworkv1.SriovNetworkPoolConfig, deletion bool) error {
1✔
125
        logger := log.Log.WithName("syncOvsHardwareOffloadMachineConfigs")
1✔
126

1✔
127
        mcpName := nc.Spec.OvsHardwareOffloadConfig.Name
1✔
128
        mcName := "00-" + mcpName + "-" + constants.OVSHWOLMachineConfigNameSuffix
1✔
129

1✔
130
        foundMC := &mcfgv1.MachineConfig{}
1✔
131
        mcp := &mcfgv1.MachineConfigPool{}
1✔
132

1✔
133
        if mcpName == "" {
2✔
134
                logger.Info("MachineConfigPool name is not defined in SriovNetworkPoolConfig", nc.GetNamespace(), nc.GetName())
1✔
135
                return nil
1✔
136
        }
1✔
137

138
        if mcpName == "master" {
1✔
139
                logger.Info("Master nodes are selected by OvsHardwareOffloadConfig.Name, ignoring.")
×
140
                return nil
×
141
        }
×
142

143
        err := r.Get(ctx, types.NamespacedName{Name: mcpName}, mcp)
1✔
144
        if err != nil {
1✔
145
                if errors.IsNotFound(err) {
×
146
                        return fmt.Errorf("machineConfigPool %s doesn't exist: %v", mcpName, err)
×
147
                }
×
148
        }
149

150
        data := render.MakeRenderData()
1✔
151
        mc, err := render.GenerateMachineConfig("bindata/manifests/switchdev-config", mcName, mcpName, true, &data)
1✔
152
        if err != nil {
1✔
153
                return err
×
154
        }
×
155

156
        err = r.Get(ctx, types.NamespacedName{Name: mcName}, foundMC)
1✔
157
        if err != nil {
2✔
158
                if errors.IsNotFound(err) {
2✔
159
                        if deletion {
1✔
160
                                logger.Info("MachineConfig has already been deleted")
×
161
                        } else {
1✔
162
                                err = r.Create(ctx, mc)
1✔
163
                                if err != nil {
1✔
164
                                        return fmt.Errorf("couldn't create MachineConfig: %v", err)
×
165
                                }
×
166
                                logger.Info("Created MachineConfig CR in MachineConfigPool", mcName, mcpName)
1✔
167
                        }
168
                } else {
×
169
                        return fmt.Errorf("failed to get MachineConfig: %v", err)
×
170
                }
×
171
        } else {
1✔
172
                if deletion {
1✔
173
                        logger.Info("offload disabled, delete MachineConfig")
×
174
                        err = r.Delete(ctx, foundMC)
×
175
                        if err != nil {
×
176
                                return fmt.Errorf("couldn't delete MachineConfig: %v", err)
×
177
                        }
×
178
                } else {
1✔
179
                        var foundIgn, renderedIgn interface{}
1✔
180
                        // The Raw config JSON string may have the fields reordered.
1✔
181
                        // For example the "path" field may come before the "contents"
1✔
182
                        // field in the rendered ignition JSON; while the found
1✔
183
                        // MachineConfig's ignition JSON would have it the other way around.
1✔
184
                        // Thus we need to unmarshal the JSON for both found and rendered
1✔
185
                        // ignition and compare.
1✔
186
                        json.Unmarshal(foundMC.Spec.Config.Raw, &foundIgn)
1✔
187
                        json.Unmarshal(mc.Spec.Config.Raw, &renderedIgn)
1✔
188
                        if !reflect.DeepEqual(foundIgn, renderedIgn) {
1✔
189
                                logger.Info("MachineConfig already exists, updating")
×
190
                                mc.SetResourceVersion(foundMC.GetResourceVersion())
×
191
                                err = r.Update(ctx, mc)
×
192
                                if err != nil {
×
193
                                        return fmt.Errorf("couldn't update MachineConfig: %v", err)
×
194
                                }
×
195
                        } else {
1✔
196
                                logger.Info("No content change, skip updating MachineConfig")
1✔
197
                        }
1✔
198
                }
199
        }
200

201
        return nil
1✔
202
}
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