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

kubeovn / kube-ovn / 13961801592

20 Mar 2025 04:11AM UTC coverage: 22.002% (-0.006%) from 22.008%
13961801592

push

github

web-flow
fix: egress network policy not work, when no pod hit matchlabel (#5089)

Signed-off-by: clyi <clyi@alauda.io>

0 of 8 new or added lines in 1 file covered. (0.0%)

3 existing lines in 2 files now uncovered.

10261 of 46637 relevant lines covered (22.0%)

0.26 hits per line

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

0.0
/pkg/controller/network_policy.go
1
package controller
2

3
import (
4
        "fmt"
5
        "maps"
6
        "reflect"
7
        "slices"
8
        "strconv"
9
        "strings"
10
        "unicode"
11

12
        "github.com/scylladb/go-set/strset"
13
        corev1 "k8s.io/api/core/v1"
14
        netv1 "k8s.io/api/networking/v1"
15
        k8serrors "k8s.io/apimachinery/pkg/api/errors"
16
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17
        "k8s.io/apimachinery/pkg/labels"
18
        utilruntime "k8s.io/apimachinery/pkg/util/runtime"
19
        "k8s.io/client-go/tools/cache"
20
        "k8s.io/klog/v2"
21
        "k8s.io/utils/set"
22

23
        kubeovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1"
24
        "github.com/kubeovn/kube-ovn/pkg/ovs"
25
        "github.com/kubeovn/kube-ovn/pkg/ovsdb/ovnnb"
26
        "github.com/kubeovn/kube-ovn/pkg/util"
27
)
28

29
func (c *Controller) enqueueAddNp(obj interface{}) {
×
30
        key := cache.MetaObjectToName(obj.(*netv1.NetworkPolicy)).String()
×
31
        klog.V(3).Infof("enqueue add network policy %s", key)
×
32
        c.updateNpQueue.Add(key)
×
33
}
×
34

35
func (c *Controller) enqueueDeleteNp(obj interface{}) {
×
36
        key := cache.MetaObjectToName(obj.(*netv1.NetworkPolicy)).String()
×
37
        klog.V(3).Infof("enqueue delete network policy %s", key)
×
38
        c.deleteNpQueue.Add(key)
×
39
}
×
40

41
func (c *Controller) enqueueUpdateNp(oldObj, newObj interface{}) {
×
42
        oldNp := oldObj.(*netv1.NetworkPolicy)
×
43
        newNp := newObj.(*netv1.NetworkPolicy)
×
44
        if !reflect.DeepEqual(oldNp.Spec, newNp.Spec) ||
×
45
                !maps.Equal(oldNp.Annotations, newNp.Annotations) {
×
46
                key := cache.MetaObjectToName(newNp).String()
×
47
                klog.V(3).Infof("enqueue update np %s", key)
×
48
                c.updateNpQueue.Add(key)
×
49
        }
×
50
}
51

52
func (c *Controller) createAsForNetpol(ns, name, direction, asName string, addresses []string) error {
×
53
        if err := c.OVNNbClient.CreateAddressSet(asName, map[string]string{
×
54
                networkPolicyKey: fmt.Sprintf("%s/%s/%s", ns, name, direction),
×
55
        }); err != nil {
×
56
                klog.Errorf("failed to create ovn address set %s for np %s/%s: %v", asName, ns, name, err)
×
57
                return err
×
58
        }
×
59

60
        if err := c.OVNNbClient.AddressSetUpdateAddress(asName, addresses...); err != nil {
×
61
                klog.Errorf("failed to set addresses %q to address set %s: %v", strings.Join(addresses, ","), asName, err)
×
62
                return err
×
63
        }
×
64

65
        return nil
×
66
}
67

68
func (c *Controller) handleUpdateNp(key string) error {
×
69
        namespace, name, err := cache.SplitMetaNamespaceKey(key)
×
70
        if err != nil {
×
71
                utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
×
72
                return nil
×
73
        }
×
74

75
        c.npKeyMutex.LockKey(key)
×
76
        defer func() { _ = c.npKeyMutex.UnlockKey(key) }()
×
77
        klog.Infof("handle add/update network policy %s", key)
×
78

×
79
        np, err := c.npsLister.NetworkPolicies(namespace).Get(name)
×
80
        if err != nil {
×
81
                if k8serrors.IsNotFound(err) {
×
82
                        return nil
×
83
                }
×
84
                klog.Error(err)
×
85
                return err
×
86
        }
87

88
        defer func() {
×
89
                if err != nil {
×
90
                        c.recorder.Eventf(np, corev1.EventTypeWarning, "CreateACLFailed", err.Error())
×
91
                }
×
92
        }()
93

94
        logEnable := false
×
95
        if np.Annotations[util.NetworkPolicyLogAnnotation] == "true" {
×
96
                logEnable = true
×
97
        }
×
98
        var logActions []string
×
99
        if np.Annotations[util.ACLActionsLogAnnotation] != "" {
×
100
                logActions = strings.Split(np.Annotations[util.ACLActionsLogAnnotation], ",")
×
101
        } else {
×
102
                logActions = []string{ovnnb.ACLActionDrop}
×
103
        }
×
104

105
        npName := np.Name
×
106
        nameArray := []rune(np.Name)
×
107
        if !unicode.IsLetter(nameArray[0]) {
×
108
                npName = "np" + np.Name
×
109
        }
×
110

111
        // TODO: ovn acl doesn't support address_set name with '-', now we replace '-' by '.'.
112
        // This may cause conflict if two np with name test-np and test.np. Maybe hash is a better solution,
113
        // but we do not want to lost the readability now.
114
        pgName := strings.ReplaceAll(fmt.Sprintf("%s.%s", npName, np.Namespace), "-", ".")
×
115
        ingressAllowAsNamePrefix := strings.ReplaceAll(fmt.Sprintf("%s.%s.ingress.allow", npName, np.Namespace), "-", ".")
×
116
        ingressExceptAsNamePrefix := strings.ReplaceAll(fmt.Sprintf("%s.%s.ingress.except", npName, np.Namespace), "-", ".")
×
117
        egressAllowAsNamePrefix := strings.ReplaceAll(fmt.Sprintf("%s.%s.egress.allow", npName, np.Namespace), "-", ".")
×
118
        egressExceptAsNamePrefix := strings.ReplaceAll(fmt.Sprintf("%s.%s.egress.except", npName, np.Namespace), "-", ".")
×
119

×
120
        if err = c.OVNNbClient.CreatePortGroup(pgName, map[string]string{networkPolicyKey: np.Namespace + "/" + npName}); err != nil {
×
121
                klog.Errorf("create port group for np %s: %v", key, err)
×
122
                return err
×
123
        }
×
124

125
        namedPortMap := c.namedPort.GetNamedPortByNs(np.Namespace)
×
126
        ports, subnetNames, err := c.fetchSelectedPorts(np.Namespace, &np.Spec.PodSelector)
×
127
        if err != nil {
×
128
                klog.Errorf("fetch ports belongs to np %s: %v", key, err)
×
129
                return err
×
130
        }
×
131

132
        var subnets []*kubeovnv1.Subnet
×
133
        protocolSet := strset.NewWithSize(2)
×
134
        for _, subnetName := range subnetNames {
×
135
                subnet, err := c.subnetsLister.Get(subnetName)
×
136
                if err != nil {
×
137
                        klog.Errorf("failed to get pod's subnet %s, %v", subnetName, err)
×
138
                        return err
×
139
                }
×
140
                subnets = append(subnets, subnet)
×
141

×
142
                if subnet.Spec.Protocol == kubeovnv1.ProtocolDual {
×
143
                        protocolSet.Add(kubeovnv1.ProtocolIPv4, kubeovnv1.ProtocolIPv6)
×
144
                } else {
×
145
                        protocolSet.Add(subnet.Spec.Protocol)
×
146
                }
×
147
        }
148
        klog.Infof("UpdateNp, releated subnets protocols %s", protocolSet.String())
×
149

×
150
        if err = c.OVNNbClient.PortGroupSetPorts(pgName, ports); err != nil {
×
151
                klog.Errorf("failed to set ports of port group %s to %v: %v", pgName, ports, err)
×
152
                return err
×
153
        }
×
154

155
        ingressACLOps, err := c.OVNNbClient.DeleteAclsOps(pgName, portGroupKey, "to-lport", nil)
×
156
        if err != nil {
×
157
                klog.Errorf("generate operations that clear np %s ingress acls: %v", key, err)
×
158
                return err
×
159
        }
×
160

161
        if hasIngressRule(np) {
×
162
                for _, protocol := range protocolSet.List() {
×
163
                        for idx, npr := range np.Spec.Ingress {
×
164
                                // A single address set must contain addresses of the same type and the name must be unique within table, so IPv4 and IPv6 address set should be different
×
165
                                ingressAllowAsName := fmt.Sprintf("%s.%s.%d", ingressAllowAsNamePrefix, protocol, idx)
×
166
                                ingressExceptAsName := fmt.Sprintf("%s.%s.%d", ingressExceptAsNamePrefix, protocol, idx)
×
167
                                aclName := fmt.Sprintf("np/%s.%s/ingress/%s/%d", npName, np.Namespace, protocol, idx)
×
168

×
169
                                var allows, excepts []string
×
170
                                if len(npr.From) == 0 {
×
171
                                        if protocol == kubeovnv1.ProtocolIPv4 {
×
172
                                                allows = []string{"0.0.0.0/0"}
×
173
                                        } else {
×
174
                                                allows = []string{"::/0"}
×
175
                                        }
×
176
                                } else {
×
177
                                        var allow, except []string
×
178
                                        for _, npp := range npr.From {
×
179
                                                if allow, except, err = c.fetchPolicySelectedAddresses(np.Namespace, protocol, npp); err != nil {
×
180
                                                        klog.Errorf("failed to fetch policy selected addresses, %v", err)
×
181
                                                        return err
×
182
                                                }
×
183
                                                allows = append(allows, allow...)
×
184
                                                excepts = append(excepts, except...)
×
185
                                        }
186
                                }
187
                                klog.Infof("UpdateNp Ingress, allows is %v, excepts is %v, log %v, protocol %v", allows, excepts, logEnable, protocol)
×
188

×
189
                                if err = c.createAsForNetpol(np.Namespace, npName, "ingress", ingressAllowAsName, allows); err != nil {
×
190
                                        klog.Error(err)
×
191
                                        return err
×
192
                                }
×
193
                                if err = c.createAsForNetpol(np.Namespace, npName, "ingress", ingressExceptAsName, excepts); err != nil {
×
194
                                        klog.Error(err)
×
195
                                        return err
×
196
                                }
×
197

198
                                npp := []netv1.NetworkPolicyPort{}
×
199
                                if len(allows) != 0 || len(excepts) != 0 {
×
200
                                        npp = npr.Ports
×
201
                                }
×
202

203
                                ops, err := c.OVNNbClient.UpdateIngressACLOps(pgName, ingressAllowAsName, ingressExceptAsName, protocol, aclName, npp, logEnable, logActions, namedPortMap)
×
204
                                if err != nil {
×
205
                                        klog.Errorf("generate operations that add ingress acls to np %s: %v", key, err)
×
206
                                        return err
×
207
                                }
×
208

209
                                ingressACLOps = append(ingressACLOps, ops...)
×
210
                        }
211
                        if len(np.Spec.Ingress) == 0 {
×
212
                                ingressAllowAsName := fmt.Sprintf("%s.%s.all", ingressAllowAsNamePrefix, protocol)
×
213
                                ingressExceptAsName := fmt.Sprintf("%s.%s.all", ingressExceptAsNamePrefix, protocol)
×
214
                                aclName := fmt.Sprintf("np/%s.%s/ingress/%s/all", npName, np.Namespace, protocol)
×
215

×
216
                                if err = c.createAsForNetpol(np.Namespace, npName, "ingress", ingressAllowAsName, nil); err != nil {
×
217
                                        klog.Error(err)
×
218
                                        return err
×
219
                                }
×
220
                                if err = c.createAsForNetpol(np.Namespace, npName, "ingress", ingressExceptAsName, nil); err != nil {
×
221
                                        klog.Error(err)
×
222
                                        return err
×
223
                                }
×
224

225
                                ops, err := c.OVNNbClient.UpdateIngressACLOps(pgName, ingressAllowAsName, ingressExceptAsName, protocol, aclName, nil, logEnable, logActions, namedPortMap)
×
226
                                if err != nil {
×
227
                                        klog.Errorf("generate operations that add ingress acls to np %s: %v", key, err)
×
228
                                        return err
×
229
                                }
×
230

231
                                ingressACLOps = append(ingressACLOps, ops...)
×
232
                        }
233
                }
234

235
                if err := c.OVNNbClient.Transact("add-ingress-acls", ingressACLOps); err != nil {
×
236
                        return fmt.Errorf("add ingress acls to %s: %w", pgName, err)
×
237
                }
×
238

239
                if err := c.OVNNbClient.SetACLLog(pgName, logEnable, true); err != nil {
×
240
                        // just log and do not return err here
×
241
                        klog.Errorf("failed to set ingress acl log for np %s, %v", key, err)
×
242
                }
×
243

244
                ass, err := c.OVNNbClient.ListAddressSets(map[string]string{
×
245
                        networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, npName, "ingress"),
×
246
                })
×
247
                if err != nil {
×
248
                        klog.Errorf("list np %s address sets: %v", key, err)
×
249
                        return err
×
250
                }
×
251

252
                // The format of asName is like "test.network.policy.test.ingress.except.0" or "test.network.policy.test.ingress.allow.0" for ingress
253
                for _, as := range ass {
×
254
                        values := strings.Split(as.Name, ".")
×
255
                        if len(values) <= 1 {
×
256
                                continue
×
257
                        }
258
                        idxStr := values[len(values)-1]
×
259
                        if idxStr == "all" {
×
260
                                continue
×
261
                        }
262
                        idx, _ := strconv.Atoi(idxStr)
×
263
                        if idx >= len(np.Spec.Ingress) {
×
264
                                if err = c.OVNNbClient.DeleteAddressSet(as.Name); err != nil {
×
265
                                        klog.Errorf("failed to delete np %s address set, %v", key, err)
×
266
                                        return err
×
267
                                }
×
268
                        }
269
                }
270
        } else {
×
271
                if err = c.OVNNbClient.DeleteAcls(pgName, portGroupKey, "to-lport", nil); err != nil {
×
272
                        klog.Errorf("delete np %s ingress acls: %v", key, err)
×
273
                        return err
×
274
                }
×
275

276
                if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
277
                        networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, npName, "ingress"),
×
278
                }); err != nil {
×
279
                        klog.Errorf("delete np %s ingress address set: %v", key, err)
×
280
                        return err
×
281
                }
×
282
        }
283

284
        egressACLOps, err := c.OVNNbClient.DeleteAclsOps(pgName, portGroupKey, "from-lport", nil)
×
285
        if err != nil {
×
286
                klog.Errorf("generate operations that clear np %s egress acls: %v", key, err)
×
287
                return err
×
288
        }
×
289

290
        if hasEgressRule(np) {
×
291
                for _, protocol := range protocolSet.List() {
×
292
                        for idx, npr := range np.Spec.Egress {
×
293
                                // A single address set must contain addresses of the same type and the name must be unique within table, so IPv4 and IPv6 address set should be different
×
294
                                egressAllowAsName := fmt.Sprintf("%s.%s.%d", egressAllowAsNamePrefix, protocol, idx)
×
295
                                egressExceptAsName := fmt.Sprintf("%s.%s.%d", egressExceptAsNamePrefix, protocol, idx)
×
296
                                aclName := fmt.Sprintf("np/%s.%s/egress/%s/%d", npName, np.Namespace, protocol, idx)
×
297

×
298
                                var allows, excepts []string
×
299
                                if len(npr.To) == 0 {
×
300
                                        if protocol == kubeovnv1.ProtocolIPv4 {
×
301
                                                allows = []string{"0.0.0.0/0"}
×
302
                                        } else {
×
303
                                                allows = []string{"::/0"}
×
304
                                        }
×
305
                                } else {
×
306
                                        var allow, except []string
×
307
                                        for _, npp := range npr.To {
×
308
                                                if allow, except, err = c.fetchPolicySelectedAddresses(np.Namespace, protocol, npp); err != nil {
×
309
                                                        klog.Errorf("failed to fetch policy selected addresses, %v", err)
×
310
                                                        return err
×
311
                                                }
×
312
                                                allows = append(allows, allow...)
×
313
                                                excepts = append(excepts, except...)
×
314
                                        }
315
                                }
316
                                klog.Infof("UpdateNp Egress, allows is %v, excepts is %v, log %v", allows, excepts, logEnable)
×
317

×
318
                                if err = c.createAsForNetpol(np.Namespace, npName, "egress", egressAllowAsName, allows); err != nil {
×
319
                                        klog.Error(err)
×
320
                                        return err
×
321
                                }
×
322
                                if err = c.createAsForNetpol(np.Namespace, npName, "egress", egressExceptAsName, excepts); err != nil {
×
323
                                        klog.Error(err)
×
324
                                        return err
×
325
                                }
×
326

NEW
327
                                npp := []netv1.NetworkPolicyPort{}
×
328
                                if len(allows) != 0 || len(excepts) != 0 {
×
NEW
329
                                        npp = npr.Ports
×
NEW
330
                                }
×
331

NEW
332
                                ops, err := c.OVNNbClient.UpdateEgressACLOps(pgName, egressAllowAsName, egressExceptAsName, protocol, aclName, npp, logEnable, logActions, namedPortMap)
×
NEW
333
                                if err != nil {
×
NEW
334
                                        klog.Errorf("generate operations that add egress acls to np %s: %v", key, err)
×
NEW
335
                                        return err
×
UNCOV
336
                                }
×
337

NEW
338
                                egressACLOps = append(egressACLOps, ops...)
×
339
                        }
340
                        if len(np.Spec.Egress) == 0 {
×
341
                                egressAllowAsName := fmt.Sprintf("%s.%s.all", egressAllowAsNamePrefix, protocol)
×
342
                                egressExceptAsName := fmt.Sprintf("%s.%s.all", egressExceptAsNamePrefix, protocol)
×
343
                                aclName := fmt.Sprintf("np/%s.%s/egress/%s/all", npName, np.Namespace, protocol)
×
344

×
345
                                if err = c.createAsForNetpol(np.Namespace, npName, "egress", egressAllowAsName, nil); err != nil {
×
346
                                        klog.Error(err)
×
347
                                        return err
×
348
                                }
×
349
                                if err = c.createAsForNetpol(np.Namespace, npName, "egress", egressExceptAsName, nil); err != nil {
×
350
                                        klog.Error(err)
×
351
                                        return err
×
352
                                }
×
353

354
                                ops, err := c.OVNNbClient.UpdateEgressACLOps(pgName, egressAllowAsName, egressExceptAsName, protocol, aclName, nil, logEnable, logActions, namedPortMap)
×
355
                                if err != nil {
×
356
                                        klog.Errorf("generate operations that add egress acls to np %s: %v", key, err)
×
357
                                        return err
×
358
                                }
×
359

360
                                egressACLOps = append(egressACLOps, ops...)
×
361
                        }
362
                }
363

364
                if err := c.OVNNbClient.Transact("add-egress-acls", egressACLOps); err != nil {
×
365
                        return fmt.Errorf("add egress acls to %s: %w", pgName, err)
×
366
                }
×
367

368
                if err := c.OVNNbClient.SetACLLog(pgName, logEnable, false); err != nil {
×
369
                        // just log and do not return err here
×
370
                        klog.Errorf("failed to set egress acl log for np %s, %v", key, err)
×
371
                }
×
372

373
                ass, err := c.OVNNbClient.ListAddressSets(map[string]string{
×
374
                        networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, npName, "egress"),
×
375
                })
×
376
                if err != nil {
×
377
                        klog.Errorf("list np %s address sets: %v", key, err)
×
378
                        return err
×
379
                }
×
380

381
                // The format of asName is like "test.network.policy.test.egress.except.0" or "test.network.policy.test.egress.allow.0" for egress
382
                for _, as := range ass {
×
383
                        values := strings.Split(as.Name, ".")
×
384
                        if len(values) <= 1 {
×
385
                                continue
×
386
                        }
387
                        idxStr := values[len(values)-1]
×
388
                        if idxStr == "all" {
×
389
                                continue
×
390
                        }
391

392
                        idx, _ := strconv.Atoi(idxStr)
×
393
                        if idx >= len(np.Spec.Egress) {
×
394
                                if err = c.OVNNbClient.DeleteAddressSet(as.Name); err != nil {
×
395
                                        klog.Errorf("delete np %s address set: %v", key, err)
×
396
                                        return err
×
397
                                }
×
398
                        }
399
                }
400
        } else {
×
401
                if err = c.OVNNbClient.DeleteAcls(pgName, portGroupKey, "from-lport", nil); err != nil {
×
402
                        klog.Errorf("delete np %s egress acls: %v", key, err)
×
403
                        return err
×
404
                }
×
405

406
                if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
407
                        networkPolicyKey: fmt.Sprintf("%s/%s/%s", np.Namespace, npName, "egress"),
×
408
                }); err != nil {
×
409
                        klog.Errorf("delete np %s egress address set: %v", key, err)
×
410
                        return err
×
411
                }
×
412
        }
413

414
        for _, subnet := range subnets {
×
415
                if err = c.OVNNbClient.CreateGatewayACL("", pgName, subnet.Spec.Gateway, subnet.Status.U2OInterconnectionIP); err != nil {
×
416
                        klog.Errorf("create gateway acl: %v", err)
×
417
                        return err
×
418
                }
×
419
        }
420
        return nil
×
421
}
422

423
func (c *Controller) handleDeleteNp(key string) error {
×
424
        namespace, name, err := cache.SplitMetaNamespaceKey(key)
×
425
        if err != nil {
×
426
                utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))
×
427
                return nil
×
428
        }
×
429

430
        c.npKeyMutex.LockKey(key)
×
431
        defer func() { _ = c.npKeyMutex.UnlockKey(key) }()
×
432
        klog.Infof("handle delete network policy %s", key)
×
433

×
434
        npName := name
×
435
        nameArray := []rune(name)
×
436
        if !unicode.IsLetter(nameArray[0]) {
×
437
                npName = "np" + name
×
438
        }
×
439

440
        pgName := strings.ReplaceAll(fmt.Sprintf("%s.%s", npName, namespace), "-", ".")
×
441
        if err = c.OVNNbClient.DeletePortGroup(pgName); err != nil {
×
442
                klog.Errorf("delete np %s port group: %v", key, err)
×
443
        }
×
444

445
        if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
446
                networkPolicyKey: fmt.Sprintf("%s/%s/%s", namespace, npName, "service"),
×
447
        }); err != nil {
×
448
                klog.Errorf("delete np %s service address set: %v", key, err)
×
449
                return err
×
450
        }
×
451

452
        if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
453
                networkPolicyKey: fmt.Sprintf("%s/%s/%s", namespace, npName, "ingress"),
×
454
        }); err != nil {
×
455
                klog.Errorf("delete np %s ingress address set: %v", key, err)
×
456
                return err
×
457
        }
×
458

459
        if err := c.OVNNbClient.DeleteAddressSets(map[string]string{
×
460
                networkPolicyKey: fmt.Sprintf("%s/%s/%s", namespace, npName, "egress"),
×
461
        }); err != nil {
×
462
                klog.Errorf("delete np %s egress address set: %v", key, err)
×
463
                return err
×
464
        }
×
465

466
        return nil
×
467
}
468

469
func (c *Controller) fetchSelectedPorts(namespace string, selector *metav1.LabelSelector) ([]string, []string, error) {
×
470
        var subnets []string
×
471
        sel, err := metav1.LabelSelectorAsSelector(selector)
×
472
        if err != nil {
×
473
                return nil, nil, fmt.Errorf("error creating label selector, %w", err)
×
474
        }
×
475
        pods, err := c.podsLister.Pods(namespace).List(sel)
×
476
        if err != nil {
×
477
                return nil, nil, fmt.Errorf("failed to list pods, %w", err)
×
478
        }
×
479

480
        ports := make([]string, 0, len(pods))
×
481
        for _, pod := range pods {
×
482
                if pod.Spec.HostNetwork {
×
483
                        continue
×
484
                }
485
                podName := c.getNameByPod(pod)
×
486
                podNets, err := c.getPodKubeovnNets(pod)
×
487
                if err != nil {
×
488
                        return nil, nil, fmt.Errorf("failed to get pod networks, %w", err)
×
489
                }
×
490

491
                for _, podNet := range podNets {
×
492
                        if !isOvnSubnet(podNet.Subnet) {
×
493
                                continue
×
494
                        }
495

496
                        if pod.Annotations[fmt.Sprintf(util.AllocatedAnnotationTemplate, podNet.ProviderName)] == "true" {
×
497
                                ports = append(ports, ovs.PodNameToPortName(podName, pod.Namespace, podNet.ProviderName))
×
498
                                // Pod selected by networkpolicy has its own subnet which is not the default subnet
×
499
                                subnets = append(subnets, podNet.Subnet.Name)
×
500
                        }
×
501
                }
502
        }
503
        subnets = slices.Compact(subnets)
×
504
        return ports, subnets, nil
×
505
}
506

507
func hasIngressRule(np *netv1.NetworkPolicy) bool {
×
508
        for _, pt := range np.Spec.PolicyTypes {
×
509
                if strings.Contains(string(pt), string(netv1.PolicyTypeIngress)) {
×
510
                        return true
×
511
                }
×
512
        }
513
        return np.Spec.Ingress != nil
×
514
}
515

516
func hasEgressRule(np *netv1.NetworkPolicy) bool {
×
517
        for _, pt := range np.Spec.PolicyTypes {
×
518
                if strings.Contains(string(pt), string(netv1.PolicyTypeEgress)) {
×
519
                        return true
×
520
                }
×
521
        }
522
        return np.Spec.Egress != nil
×
523
}
524

525
func (c *Controller) fetchPolicySelectedAddresses(namespace, protocol string, npp netv1.NetworkPolicyPeer) ([]string, []string, error) {
×
526
        selectedAddresses := []string{}
×
527
        exceptAddresses := []string{}
×
528

×
529
        // ingress.from.ipblock or egress.to.ipblock
×
530
        if npp.IPBlock != nil && util.CheckProtocol(npp.IPBlock.CIDR) == protocol {
×
531
                selectedAddresses = append(selectedAddresses, npp.IPBlock.CIDR)
×
532
                if npp.IPBlock.Except != nil {
×
533
                        exceptAddresses = append(exceptAddresses, npp.IPBlock.Except...)
×
534
                }
×
535
        }
536
        if npp.NamespaceSelector == nil && npp.PodSelector == nil {
×
537
                return selectedAddresses, exceptAddresses, nil
×
538
        }
×
539

540
        selectedNs := []string{}
×
541
        if npp.NamespaceSelector == nil {
×
542
                selectedNs = append(selectedNs, namespace)
×
543
        } else {
×
544
                sel, err := metav1.LabelSelectorAsSelector(npp.NamespaceSelector)
×
545
                if err != nil {
×
546
                        return nil, nil, fmt.Errorf("error creating label selector, %w", err)
×
547
                }
×
548
                nss, err := c.namespacesLister.List(sel)
×
549
                if err != nil {
×
550
                        return nil, nil, fmt.Errorf("failed to list ns, %w", err)
×
551
                }
×
552
                for _, ns := range nss {
×
553
                        selectedNs = append(selectedNs, ns.Name)
×
554
                }
×
555
        }
556

557
        var sel labels.Selector
×
558
        if npp.PodSelector == nil {
×
559
                sel = labels.Everything()
×
560
        } else {
×
561
                sel, _ = metav1.LabelSelectorAsSelector(npp.PodSelector)
×
562
        }
×
563

564
        for _, ns := range selectedNs {
×
565
                pods, err := c.podsLister.Pods(ns).List(sel)
×
566
                if err != nil {
×
567
                        return nil, nil, fmt.Errorf("failed to list pod, %w", err)
×
568
                }
×
569
                svcs, err := c.servicesLister.Services(ns).List(labels.Everything())
×
570
                if err != nil {
×
571
                        klog.Errorf("failed to list svc, %v", err)
×
572
                        return nil, nil, fmt.Errorf("failed to list svc, %w", err)
×
573
                }
×
574

575
                for _, pod := range pods {
×
576
                        podNets, err := c.getPodKubeovnNets(pod)
×
577
                        if err != nil {
×
578
                                klog.Errorf("failed to get pod nets %v", err)
×
579
                                return nil, nil, err
×
580
                        }
×
581
                        for _, podNet := range podNets {
×
582
                                podIPAnnotation := pod.Annotations[fmt.Sprintf(util.IPAddressAnnotationTemplate, podNet.ProviderName)]
×
583
                                podIPs := strings.Split(podIPAnnotation, ",")
×
584
                                for _, podIP := range podIPs {
×
585
                                        if podIP != "" && util.CheckProtocol(podIP) == protocol {
×
586
                                                selectedAddresses = append(selectedAddresses, podIP)
×
587
                                        }
×
588
                                }
589
                                if len(svcs) == 0 {
×
590
                                        continue
×
591
                                }
592

593
                                svcIPs, err := svcMatchPods(svcs, pod, protocol)
×
594
                                if err != nil {
×
595
                                        return nil, nil, err
×
596
                                }
×
597
                                selectedAddresses = append(selectedAddresses, svcIPs...)
×
598
                        }
599
                }
600
        }
601
        return selectedAddresses, exceptAddresses, nil
×
602
}
603

604
func svcMatchPods(svcs []*corev1.Service, pod *corev1.Pod, protocol string) ([]string, error) {
×
605
        matchSvcs := []string{}
×
606
        // find svc ip by pod's info
×
607
        for _, svc := range svcs {
×
608
                isMatch, err := isSvcMatchPod(svc, pod)
×
609
                if err != nil {
×
610
                        return nil, err
×
611
                }
×
612
                if isMatch {
×
613
                        clusterIPs := util.ServiceClusterIPs(*svc)
×
614
                        protocolClusterIPs := getProtocolSvcIP(clusterIPs, protocol)
×
615
                        if len(protocolClusterIPs) != 0 {
×
616
                                matchSvcs = append(matchSvcs, protocolClusterIPs...)
×
617
                        }
×
618
                }
619
        }
620
        return matchSvcs, nil
×
621
}
622

623
func getProtocolSvcIP(clusterIPs []string, protocol string) []string {
×
624
        protocolClusterIPs := []string{}
×
625
        for _, clusterIP := range clusterIPs {
×
626
                if clusterIP != "" && clusterIP != corev1.ClusterIPNone && util.CheckProtocol(clusterIP) == protocol {
×
627
                        protocolClusterIPs = append(protocolClusterIPs, clusterIP)
×
628
                }
×
629
        }
630
        return protocolClusterIPs
×
631
}
632

633
func isSvcMatchPod(svc *corev1.Service, pod *corev1.Pod) (bool, error) {
×
634
        ss := metav1.SetAsLabelSelector(svc.Spec.Selector)
×
635
        sel, err := metav1.LabelSelectorAsSelector(ss)
×
636
        if err != nil {
×
637
                return false, fmt.Errorf("error fetch label selector, %w", err)
×
638
        }
×
639
        if pod.Labels == nil {
×
640
                return false, nil
×
641
        }
×
642
        if sel.Matches(labels.Set(pod.Labels)) {
×
643
                return true, nil
×
644
        }
×
645
        return false, nil
×
646
}
647

648
func (c *Controller) podMatchNetworkPolicies(pod *corev1.Pod) []string {
×
649
        podNs, err := c.namespacesLister.Get(pod.Namespace)
×
650
        if err != nil {
×
651
                klog.Errorf("failed to get namespace %s: %v", pod.Namespace, err)
×
652
                utilruntime.HandleError(err)
×
653
                return nil
×
654
        }
×
655

656
        nps, err := c.npsLister.NetworkPolicies(corev1.NamespaceAll).List(labels.Everything())
×
657
        if err != nil {
×
658
                klog.Errorf("failed to list network policies: %v", err)
×
659
                utilruntime.HandleError(err)
×
660
                return nil
×
661
        }
×
662

663
        match := []string{}
×
664
        for _, np := range nps {
×
665
                if isPodMatchNetworkPolicy(pod, *podNs, np, np.Namespace) {
×
666
                        match = append(match, cache.MetaObjectToName(np).String())
×
667
                }
×
668
        }
669
        return match
×
670
}
671

672
func (c *Controller) svcMatchNetworkPolicies(svc *corev1.Service) ([]string, error) {
×
673
        // find all match pod
×
674
        sel := labels.Set(svc.Spec.Selector).AsSelector()
×
675
        pods, err := c.podsLister.Pods(svc.Namespace).List(sel)
×
676
        if err != nil {
×
677
                return nil, fmt.Errorf("failed to list pods, %w", err)
×
678
        }
×
679

680
        // find all match netpol
681
        nps, err := c.npsLister.NetworkPolicies(corev1.NamespaceAll).List(labels.Everything())
×
682
        if err != nil {
×
683
                return nil, fmt.Errorf("failed to list netpols, %w", err)
×
684
        }
×
685
        match := set.New[string]()
×
686
        ns, _ := c.namespacesLister.Get(svc.Namespace)
×
687
        for _, pod := range pods {
×
688
                for _, np := range nps {
×
689
                        key := cache.MetaObjectToName(np).String()
×
690
                        if match.Has(key) {
×
691
                                continue
×
692
                        }
693
                        if isPodMatchNetworkPolicy(pod, *ns, np, np.Namespace) {
×
694
                                match.Insert(key)
×
695
                                klog.V(3).Infof("svc %s/%s match np %s", svc.Namespace, svc.Name, key)
×
696
                        }
×
697
                }
698
        }
699
        return match.UnsortedList(), nil
×
700
}
701

702
func isPodMatchNetworkPolicy(pod *corev1.Pod, podNs corev1.Namespace, policy *netv1.NetworkPolicy, policyNs string) bool {
×
703
        sel, _ := metav1.LabelSelectorAsSelector(&policy.Spec.PodSelector)
×
704
        if pod.Labels == nil {
×
705
                pod.Labels = map[string]string{}
×
706
        }
×
707
        if podNs.Name == policyNs && sel.Matches(labels.Set(pod.Labels)) {
×
708
                return true
×
709
        }
×
710
        for _, npr := range policy.Spec.Ingress {
×
711
                for _, npp := range npr.From {
×
712
                        if isPodMatchPolicyPeer(pod, podNs, npp, policyNs) {
×
713
                                return true
×
714
                        }
×
715
                }
716
        }
717
        for _, npr := range policy.Spec.Egress {
×
718
                for _, npp := range npr.To {
×
719
                        if isPodMatchPolicyPeer(pod, podNs, npp, policyNs) {
×
720
                                return true
×
721
                        }
×
722
                }
723
        }
724
        return false
×
725
}
726

727
func isPodMatchPolicyPeer(pod *corev1.Pod, podNs corev1.Namespace, policyPeer netv1.NetworkPolicyPeer, policyNs string) bool {
×
728
        if policyPeer.IPBlock != nil {
×
729
                return false
×
730
        }
×
731
        if policyPeer.NamespaceSelector == nil {
×
732
                if policyNs != podNs.Name {
×
733
                        return false
×
734
                }
×
735
        } else {
×
736
                nsSel, _ := metav1.LabelSelectorAsSelector(policyPeer.NamespaceSelector)
×
737
                if podNs.Labels == nil {
×
738
                        podNs.Labels = map[string]string{}
×
739
                }
×
740
                if !nsSel.Matches(labels.Set(podNs.Labels)) {
×
741
                        return false
×
742
                }
×
743
        }
744

745
        if policyPeer.PodSelector == nil {
×
746
                return true
×
747
        }
×
748

749
        sel, _ := metav1.LabelSelectorAsSelector(policyPeer.PodSelector)
×
750
        if pod.Labels == nil {
×
751
                pod.Labels = map[string]string{}
×
752
        }
×
753
        return sel.Matches(labels.Set(pod.Labels))
×
754
}
755

756
func (c *Controller) namespaceMatchNetworkPolicies(ns *corev1.Namespace) []string {
×
757
        nps, _ := c.npsLister.NetworkPolicies(corev1.NamespaceAll).List(labels.Everything())
×
758
        match := make([]string, 0, len(nps))
×
759
        for _, np := range nps {
×
760
                if isNamespaceMatchNetworkPolicy(ns, np) {
×
761
                        match = append(match, cache.MetaObjectToName(np).String())
×
762
                }
×
763
        }
764
        return match
×
765
}
766

767
func isNamespaceMatchNetworkPolicy(ns *corev1.Namespace, policy *netv1.NetworkPolicy) bool {
×
768
        for _, npr := range policy.Spec.Ingress {
×
769
                for _, npp := range npr.From {
×
770
                        if npp.NamespaceSelector != nil {
×
771
                                nsSel, _ := metav1.LabelSelectorAsSelector(npp.NamespaceSelector)
×
772
                                if ns.Labels == nil {
×
773
                                        ns.Labels = map[string]string{}
×
774
                                }
×
775
                                if nsSel.Matches(labels.Set(ns.Labels)) {
×
776
                                        return true
×
777
                                }
×
778
                        }
779
                }
780
        }
781

782
        for _, npr := range policy.Spec.Egress {
×
783
                for _, npp := range npr.To {
×
784
                        if npp.NamespaceSelector != nil {
×
785
                                nsSel, _ := metav1.LabelSelectorAsSelector(npp.NamespaceSelector)
×
786
                                if ns.Labels == nil {
×
787
                                        ns.Labels = map[string]string{}
×
788
                                }
×
789
                                if nsSel.Matches(labels.Set(ns.Labels)) {
×
790
                                        return true
×
791
                                }
×
792
                        }
793
                }
794
        }
795
        return false
×
796
}
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