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

k8snetworkplumbingwg / sriov-network-operator / 11775513002

11 Nov 2024 09:12AM UTC coverage: 47.024% (+1.4%) from 45.603%
11775513002

Pull #747

github

web-flow
Merge baa41c97a into 92fee7bec
Pull Request #747: Redesign device plugin reset

86 of 118 new or added lines in 4 files covered. (72.88%)

9 existing lines in 2 files now uncovered.

7103 of 15105 relevant lines covered (47.02%)

0.52 hits per line

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

45.45
/pkg/utils/cluster.go
1
package utils
2

3
import (
4
        "context"
5
        "fmt"
6
        "os"
7

8
        configv1 "github.com/openshift/api/config/v1"
9
        corev1 "k8s.io/api/core/v1"
10
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11
        "k8s.io/apimachinery/pkg/types"
12
        "sigs.k8s.io/controller-runtime/pkg/client"
13
        "sigs.k8s.io/controller-runtime/pkg/log"
14

15
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts"
16
)
17

18
const (
19
        // default Infrastructure resource name for Openshift
20
        infraResourceName        = "cluster"
21
        workerRoleName           = "worker"
22
        masterRoleName           = "master"
23
        workerNodeLabelKey       = "node-role.kubernetes.io/worker"
24
        masterNodeLabelKey       = "node-role.kubernetes.io/master"
25
        controlPlaneNodeLabelKey = "node-role.kubernetes.io/control-plane"
26
)
27

28
func getNodeRole(node corev1.Node) string {
×
29
        for k := range node.Labels {
×
30
                if k == workerNodeLabelKey {
×
31
                        return workerRoleName
×
32
                } else if k == masterNodeLabelKey || k == controlPlaneNodeLabelKey {
×
33
                        return masterRoleName
×
34
                }
×
35
        }
36
        return ""
×
37
}
38

39
func IsSingleNodeCluster(c client.Client) (bool, error) {
×
40
        if os.Getenv("CLUSTER_TYPE") == consts.ClusterTypeOpenshift {
×
41
                topo, err := openshiftControlPlaneTopologyStatus(c)
×
42
                if err != nil {
×
43
                        return false, err
×
44
                }
×
45
                if topo == configv1.SingleReplicaTopologyMode {
×
46
                        return true, nil
×
47
                }
×
48
                return false, nil
×
49
        }
50
        return k8sSingleNodeClusterStatus(c)
×
51
}
52

53
// IsExternalControlPlaneCluster detects control plane location of the cluster.
54
// On OpenShift, the control plane topology is configured in configv1.Infrastucture struct.
55
// On kubernetes, it is determined by which node the sriov operator is scheduled on. If operator
56
// pod is schedule on worker node, it is considered as external control plane.
57
func IsExternalControlPlaneCluster(c client.Client) (bool, error) {
×
58
        if os.Getenv("CLUSTER_TYPE") == consts.ClusterTypeOpenshift {
×
59
                topo, err := openshiftControlPlaneTopologyStatus(c)
×
60
                if err != nil {
×
61
                        return false, err
×
62
                }
×
63
                if topo == "External" {
×
64
                        return true, nil
×
65
                }
×
66
        } else if os.Getenv("CLUSTER_TYPE") == consts.ClusterTypeKubernetes {
×
67
                role, err := operatorNodeRole(c)
×
68
                if err != nil {
×
69
                        return false, err
×
70
                }
×
71
                if role == workerRoleName {
×
72
                        return true, nil
×
73
                }
×
74
        }
75
        return false, nil
×
76
}
77

78
func k8sSingleNodeClusterStatus(c client.Client) (bool, error) {
×
79
        nodeList := &corev1.NodeList{}
×
80
        err := c.List(context.TODO(), nodeList)
×
81
        if err != nil {
×
82
                log.Log.Error(err, "k8sSingleNodeClusterStatus(): Failed to list nodes")
×
83
                return false, err
×
84
        }
×
85

86
        if len(nodeList.Items) == 1 {
×
87
                log.Log.Info("k8sSingleNodeClusterStatus(): one node found in the cluster")
×
88
                return true, nil
×
89
        }
×
90
        return false, nil
×
91
}
92

93
// operatorNodeRole returns role of the node where operator is scheduled on
94
func operatorNodeRole(c client.Client) (string, error) {
×
95
        node := corev1.Node{}
×
96
        err := c.Get(context.TODO(), types.NamespacedName{Name: os.Getenv("NODE_NAME")}, &node)
×
97
        if err != nil {
×
98
                log.Log.Error(err, "k8sIsExternalTopologyMode(): Failed to get node")
×
99
                return "", err
×
100
        }
×
101

102
        return getNodeRole(node), nil
×
103
}
104

105
func openshiftControlPlaneTopologyStatus(c client.Client) (configv1.TopologyMode, error) {
×
106
        infra := &configv1.Infrastructure{}
×
107
        err := c.Get(context.TODO(), types.NamespacedName{Name: infraResourceName}, infra)
×
108
        if err != nil {
×
109
                return "", fmt.Errorf("openshiftControlPlaneTopologyStatus(): Failed to get Infrastructure (name: %s): %v", infraResourceName, err)
×
110
        }
×
111
        return infra.Status.ControlPlaneTopology, nil
×
112
}
113

114
// ObjectHasAnnotationKey checks if a kubernetes object already contains annotation
115
func ObjectHasAnnotationKey(obj metav1.Object, annoKey string) bool {
×
116
        _, hasKey := obj.GetAnnotations()[annoKey]
×
117
        return hasKey
×
118
}
×
119

120
// ObjectHasAnnotation checks if a kubernetes object already contains annotation
121
func ObjectHasAnnotation(obj metav1.Object, annoKey string, value string) bool {
1✔
122
        if anno, ok := obj.GetAnnotations()[annoKey]; ok && (anno == value) {
2✔
123
                return true
1✔
124
        }
1✔
125
        return false
1✔
126
}
127

128
// AnnotateObject adds annotation to a kubernetes object
129
func AnnotateObject(ctx context.Context, obj client.Object, key, value string, c client.Client) error {
1✔
130
        newObj := obj.DeepCopyObject().(client.Object)
1✔
131
        if newObj.GetAnnotations() == nil {
2✔
132
                newObj.SetAnnotations(map[string]string{})
1✔
133
        }
1✔
134

135
        if newObj.GetAnnotations()[key] != value {
2✔
136
                log.Log.V(2).Info("AnnotateObject(): Annotate object",
1✔
137
                        "objectName", obj.GetName(),
1✔
138
                        "objectKind", obj.GetObjectKind(),
1✔
139
                        "annotationKey", key,
1✔
140
                        "annotationValue", value)
1✔
141
                newObj.GetAnnotations()[key] = value
1✔
142
                patch := client.MergeFrom(obj)
1✔
143
                err := c.Patch(ctx,
1✔
144
                        newObj, patch)
1✔
145
                if err != nil {
2✔
146
                        log.Log.Error(err, "annotateObject(): Failed to patch object")
1✔
147
                        return err
1✔
148
                }
1✔
149
        }
150

151
        return nil
1✔
152
}
153

154
// AnnotateNode add annotation to a node
155
func AnnotateNode(ctx context.Context, nodeName string, key, value string, c client.Client) error {
1✔
156
        node := &corev1.Node{}
1✔
157
        err := c.Get(context.TODO(), client.ObjectKey{Name: nodeName}, node)
1✔
158
        if err != nil {
1✔
159
                return err
×
160
        }
×
161

162
        return AnnotateObject(ctx, node, key, value, c)
1✔
163
}
164

165
// labelObject adds label to a kubernetes object
166
func labelObject(ctx context.Context, obj client.Object, key, value string, c client.Client) error {
1✔
167
        newObj := obj.DeepCopyObject().(client.Object)
1✔
168
        if newObj.GetLabels() == nil {
1✔
NEW
169
                newObj.SetLabels(map[string]string{})
×
NEW
170
        }
×
171

172
        if newObj.GetLabels()[key] != value {
2✔
173
                log.Log.V(2).Info("labelObject(): label object",
1✔
174
                        "objectName", obj.GetName(),
1✔
175
                        "objectKind", obj.GetObjectKind(),
1✔
176
                        "labelKey", key,
1✔
177
                        "labelValue", value)
1✔
178
                newObj.GetLabels()[key] = value
1✔
179
                patch := client.MergeFrom(obj)
1✔
180
                err := c.Patch(ctx,
1✔
181
                        newObj, patch)
1✔
182
                if err != nil {
1✔
NEW
183
                        log.Log.Error(err, "labelObject(): Failed to patch object")
×
NEW
184
                        return err
×
NEW
185
                }
×
186
        }
187

188
        return nil
1✔
189
}
190

191
// removeLabelObject remove a label from a kubernetes object
192
func removeLabelObject(ctx context.Context, obj client.Object, key string, c client.Client) error {
1✔
193
        newObj := obj.DeepCopyObject().(client.Object)
1✔
194
        if newObj.GetLabels() == nil {
1✔
NEW
195
                newObj.SetLabels(map[string]string{})
×
NEW
196
        }
×
197

198
        _, exist := newObj.GetLabels()[key]
1✔
199
        if exist {
2✔
200
                log.Log.V(2).Info("removeLabelObject(): remove label from object",
1✔
201
                        "objectName", obj.GetName(),
1✔
202
                        "objectKind", obj.GetObjectKind(),
1✔
203
                        "labelKey", key)
1✔
204
                delete(newObj.GetLabels(), key)
1✔
205
                patch := client.MergeFrom(obj)
1✔
206
                err := c.Patch(ctx,
1✔
207
                        newObj, patch)
1✔
208
                if err != nil {
1✔
NEW
209
                        log.Log.Error(err, "removeLabelObject(): Failed to patch object")
×
NEW
210
                        return err
×
NEW
211
                }
×
212
        }
213

214
        return nil
1✔
215
}
216

217
// LabelNode add label to a node
218
func LabelNode(ctx context.Context, nodeName string, key, value string, c client.Client) error {
1✔
219
        node := &corev1.Node{}
1✔
220
        err := c.Get(context.TODO(), client.ObjectKey{Name: nodeName}, node)
1✔
221
        if err != nil {
1✔
NEW
222
                return err
×
NEW
223
        }
×
224

225
        return labelObject(ctx, node, key, value, c)
1✔
226
}
227

228
func RemoveLabelFromNode(ctx context.Context, nodeName string, key string, c client.Client) error {
1✔
229
        node := &corev1.Node{}
1✔
230
        err := c.Get(context.TODO(), client.ObjectKey{Name: nodeName}, node)
1✔
231
        if err != nil {
1✔
NEW
232
                return err
×
NEW
233
        }
×
234

235
        return removeLabelObject(ctx, node, key, c)
1✔
236
}
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