From 9af14872b02d41a27d065d442fed94fa05d5b236 Mon Sep 17 00:00:00 2001 From: Mazdak Nasab Date: Mon, 9 Feb 2026 14:50:28 -0800 Subject: [PATCH 1/7] ClusterNetworkPolicy: support generic protocols --- go.mod | 2 +- go.sum | 4 +- libcalico-go/Makefile | 2 +- .../k8s/conversion/clusternetworkpolicy.go | 97 +++--- .../conversion/clusternetworkpolicy_test.go | 297 +++++++++++------- .../globalnetworkpolicyprocessor_test.go | 18 +- 6 files changed, 242 insertions(+), 178 deletions(-) diff --git a/go.mod b/go.mod index bb7f4b9f04b..6d5faf7efc4 100644 --- a/go.mod +++ b/go.mod @@ -120,7 +120,7 @@ require ( sigs.k8s.io/controller-runtime v0.22.3 sigs.k8s.io/kind v0.30.0 sigs.k8s.io/knftables v0.0.19 - sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d + sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/yaml v1.6.0 ) diff --git a/go.sum b/go.sum index 7e35a627d33..97f16260ea3 100644 --- a/go.sum +++ b/go.sum @@ -1087,8 +1087,8 @@ sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM= sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78= sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po= -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d h1:mdzh06UcLpN7gcODfc4NqSNtDI0NWLJ2jlS4KhchgG0= -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d/go.mod h1:xYIHRc47QPAIiPkl+oXfu5we8jACNlt7WuKc7ZP0sGU= +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 h1:PLQPDVCmIitKwwC16gD13TqT2lgHnUrz51g68IVpWcQ= +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449/go.mod h1:xYIHRc47QPAIiPkl+oXfu5we8jACNlt7WuKc7ZP0sGU= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= diff --git a/libcalico-go/Makefile b/libcalico-go/Makefile index 685a245f448..8b19f027d0c 100644 --- a/libcalico-go/Makefile +++ b/libcalico-go/Makefile @@ -10,7 +10,7 @@ KIND_CONFIG = $(KIND_DIR)/kind-single.config # NETPOL_CNP_REF = refs/heads/main # For a commit, just use the commit ID: # NETPOL_CNP_REF = -NETPOL_CNP_REF = 1f80acbe25809162f3f81ffa254eb24318ea387b +NETPOL_CNP_REF = 196cf8e0d449e108f4bb36cb97e127a37d24e428 NETPOL_CNP_CRD_URL = https://raw.githubusercontent.com/kubernetes-sigs/network-policy-api/$(NETPOL_CNP_REF)/config/crd/standard NETPOL_CNP_CRD = policy.networking.k8s.io_clusternetworkpolicies.yaml diff --git a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go index 5927ce91c55..92ec9ca9f8f 100644 --- a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go +++ b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go @@ -1,4 +1,4 @@ -// Copyright (c) 2025 Tigera, Inc. All rights reserved. +// Copyright (c) 2025-2026 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -165,7 +165,7 @@ func k8sClusterNetPolIngressRuleToCalico(rule clusternetpol.ClusterNetworkPolicy if err != nil { return nil, err } - return combinePortsWithCNPIngressPeers(rule.Ports, rule.From, rule.Name, action) + return combinePortsWithCNPIngressPeers(rule.Protocols, rule.From, rule.Name, action) } func k8sClusterNetPolEgressRuleToCalico(rule clusternetpol.ClusterNetworkPolicyEgressRule) ([]apiv3.Rule, error) { @@ -173,7 +173,7 @@ func k8sClusterNetPolEgressRuleToCalico(rule clusternetpol.ClusterNetworkPolicyE if err != nil { return nil, err } - return combinePortsWithCNPEgressPeers(rule.Ports, rule.To, rule.Name, action) + return combinePortsWithCNPEgressPeers(rule.Protocols, rule.To, rule.Name, action) } func K8sClusterNetworkPolicyActionToCalico(action clusternetpol.ClusterNetworkPolicyRuleAction) (apiv3.Action, error) { @@ -189,12 +189,12 @@ func K8sClusterNetworkPolicyActionToCalico(action clusternetpol.ClusterNetworkPo } func combinePortsWithCNPIngressPeers( - cnpPorts *[]clusternetpol.ClusterNetworkPolicyPort, + cnpProtocols []clusternetpol.ClusterNetworkPolicyProtocol, cnpPeers []clusternetpol.ClusterNetworkPolicyIngressPeer, ruleName string, action apiv3.Action, ) (rules []apiv3.Rule, err error) { - protocolPorts, sortedProtocols, err := unpackCNPPorts(cnpPorts) + protocolPorts, sortedProtocols, err := unpackCNPProtocols(cnpProtocols) if err != nil { return nil, err } @@ -248,12 +248,12 @@ func combinePortsWithCNPIngressPeers( } func combinePortsWithCNPEgressPeers( - cnpPorts *[]clusternetpol.ClusterNetworkPolicyPort, + cnpProtocols []clusternetpol.ClusterNetworkPolicyProtocol, cnpPeers []clusternetpol.ClusterNetworkPolicyEgressPeer, ruleName string, action apiv3.Action, ) (rules []apiv3.Rule, err error) { - protocolPorts, sortedProtocols, err := unpackCNPPorts(cnpPorts) + protocolPorts, sortedProtocols, err := unpackCNPProtocols(cnpProtocols) if err != nil { return nil, err } @@ -317,20 +317,20 @@ func combinePortsWithCNPEgressPeers( return rules, nil } -func unpackCNPPorts(k8sPorts *[]clusternetpol.ClusterNetworkPolicyPort) ( +func unpackCNPProtocols(cnpProtocols []clusternetpol.ClusterNetworkPolicyProtocol) ( map[string][]numorstring.Port, []string, error, ) { // If there are no ports, represent that as zero struct. - ports := []clusternetpol.ClusterNetworkPolicyPort{{}} - if k8sPorts != nil && len(*k8sPorts) != 0 { - ports = *k8sPorts + protocols := []clusternetpol.ClusterNetworkPolicyProtocol{{}} + if cnpProtocols != nil && len(cnpProtocols) != 0 { + protocols = cnpProtocols } protocolPorts := map[string][]numorstring.Port{} - for _, port := range ports { - protocol, calicoPort, err := k8sCNPPortToCalicoFields(&port) + for _, p := range protocols { + protocol, calicoPort, err := k8sCNPPortToCalicoFields(&p) if err != nil { return nil, nil, fmt.Errorf("failed to parse k8s port: %s", err) } @@ -354,61 +354,60 @@ func unpackCNPPorts(k8sPorts *[]clusternetpol.ClusterNetworkPolicyPort) ( } } - protocols := make([]string, 0, len(protocolPorts)) - for k := range protocolPorts { - protocols = append(protocols, k) + protos := make([]string, 0, len(protocolPorts)) + for p := range protocolPorts { + protos = append(protos, p) } // Ensure deterministic output - sort.Strings(protocols) - return protocolPorts, protocols, nil + sort.Strings(protos) + return protocolPorts, protos, nil } -func k8sCNPPortToCalicoFields(port *clusternetpol.ClusterNetworkPolicyPort) ( +func k8sCNPPortToCalicoFields(cnpProto *clusternetpol.ClusterNetworkPolicyProtocol) ( protocol *numorstring.Protocol, dstPort *numorstring.Port, err error, ) { // If no port info, return zero values for all fields (protocol, dstPorts). - if port == nil { + if cnpProto == nil { return } - // Only one of the PortNumber or PortRange is set. - if port.PortNumber != nil { - dstPort = k8sCNPPortToCalico(port.PortNumber) - proto := ensureProtocol(port.PortNumber.Protocol) - protocol = k8sProtocolToCalico(&proto) - return + + if cnpProto.TCP != nil { + dstPort, err = k8sCNPPortToCalico(cnpProto.TCP.DestinationPort) + p := numorstring.ProtocolFromString(numorstring.ProtocolTCP) + protocol = &p } - if port.PortRange != nil { - dstPort, err = k8sCNPPortRangeToCalico(port.PortRange) - if err != nil { - return - } - proto := ensureProtocol(port.PortRange.Protocol) - protocol = k8sProtocolToCalico(&proto) - return + + if cnpProto.UDP != nil { + dstPort, err = k8sCNPPortToCalico(cnpProto.UDP.DestinationPort) + p := numorstring.ProtocolFromString(numorstring.ProtocolUDP) + protocol = &p } - // TODO: Add support for NamedPorts - return -} -func k8sCNPPortToCalico(port *clusternetpol.Port) *numorstring.Port { - if port == nil { - return nil + if cnpProto.SCTP != nil { + dstPort, err = k8sCNPPortToCalico(cnpProto.SCTP.DestinationPort) + p := numorstring.ProtocolFromString(numorstring.ProtocolSCTP) + protocol = &p } - p := numorstring.SinglePort(uint16(port.Port)) - return &p + + return } -func k8sCNPPortRangeToCalico(port *clusternetpol.PortRange) (*numorstring.Port, error) { - if port == nil { - return nil, nil +func k8sCNPPortToCalico(port *clusternetpol.Port) (*numorstring.Port, error) { + // Only one of the Number or Range is set. + if port.Number != 0 { + p := numorstring.SinglePort(uint16(port.Number)) + return &p, nil } - p, err := numorstring.PortFromRange(uint16(port.Start), uint16(port.End)) - if err != nil { - return nil, err + if port.Range != nil { + p, err := numorstring.PortFromRange(uint16(port.Range.Start), uint16(port.Range.End)) + if err != nil { + return nil, err + } + return &p, nil } - return &p, nil + return nil, nil } func k8sClusterNetworkPolicyToCalicoMetadata(ruleName string) *apiv3.RuleMetadata { diff --git a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy_test.go b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy_test.go index ae38da53d9f..32747fb14ae 100644 --- a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy_test.go +++ b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2025 Tigera, Inc. All rights reserved. +// Copyright (c) 2025-2026 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ import ( . "github.com/onsi/gomega" apiv3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3" "github.com/projectcalico/api/pkg/lib/numorstring" - kapiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" clusternetpol "sigs.k8s.io/network-policy-api/apis/v1alpha2" @@ -29,9 +28,11 @@ import ( var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { It("should parse a basic k8s ClusterNetworkPolicy to a GlobalNetworkPolicy", func() { - ports := []clusternetpol.ClusterNetworkPolicyPort{{ - PortNumber: &clusternetpol.Port{ - Port: 80, + protocols := []clusternetpol.ClusterNetworkPolicyProtocol{{ + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, }, }} cnp := clusternetpol.ClusterNetworkPolicy{ @@ -52,9 +53,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Ingress: []clusternetpol.ClusterNetworkPolicyIngressRule{ { - Name: "The first ingress rule", - Action: "Accept", - Ports: &ports, + Name: "The first ingress rule", + Action: "Accept", + Protocols: protocols, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -95,12 +96,20 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }) It("should drop rules with invalid action in a k8s ClusterNetworkPolicy", func() { - ports := []clusternetpol.ClusterNetworkPolicyPort{ + protocols := []clusternetpol.ClusterNetworkPolicyProtocol{ { - PortNumber: &clusternetpol.Port{Port: 80}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, + }, }, { - PortRange: &clusternetpol.PortRange{Start: 2000, End: 3000}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Range: &clusternetpol.PortRange{Start: 2000, End: 3000}, + }, + }, }, } cnp := clusternetpol.ClusterNetworkPolicy{ @@ -135,9 +144,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, }, { - Name: "A random ingress rule 2", - Action: "Accept", - Ports: &ports, + Name: "A random ingress rule 2", + Action: "Accept", + Protocols: protocols, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -152,9 +161,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Egress: []clusternetpol.ClusterNetworkPolicyEgressRule{ { - Name: "A random egress rule", - Action: "Deny", - Ports: &ports, + Name: "A random egress rule", + Action: "Deny", + Protocols: protocols, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -335,20 +344,36 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }) It("should drop rules with invalid ports in a k8s ClusterNetworkPolicy", func() { - goodPorts := []clusternetpol.ClusterNetworkPolicyPort{ + goodProtos := []clusternetpol.ClusterNetworkPolicyProtocol{ { - PortNumber: &clusternetpol.Port{Port: 80}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, + }, }, { - PortRange: &clusternetpol.PortRange{Start: 2000, End: 3000}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Range: &clusternetpol.PortRange{Start: 2000, End: 3000}, + }, + }, }, } - badPorts := []clusternetpol.ClusterNetworkPolicyPort{ + badProtos := []clusternetpol.ClusterNetworkPolicyProtocol{ { - PortNumber: &clusternetpol.Port{Port: 80}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, + }, }, { - PortRange: &clusternetpol.PortRange{Start: 1000, End: 10}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Range: &clusternetpol.PortRange{Start: 1000, End: 10}, + }, + }, }, } @@ -370,9 +395,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Ingress: []clusternetpol.ClusterNetworkPolicyIngressRule{ { - Name: "A random ingress rule", - Action: "Accept", - Ports: &badPorts, + Name: "A random ingress rule", + Action: "Accept", + Protocols: badProtos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -385,9 +410,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, }, { - Name: "A random ingress rule 2", - Action: "Pass", - Ports: &goodPorts, + Name: "A random ingress rule 2", + Action: "Pass", + Protocols: goodProtos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -402,9 +427,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Egress: []clusternetpol.ClusterNetworkPolicyEgressRule{ { - Name: "A random egress rule", - Action: "Deny", - Ports: &goodPorts, + Name: "A random egress rule", + Action: "Deny", + Protocols: goodProtos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -417,9 +442,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, }, { - Name: "A random egress rule 2", - Action: "Accept", - Ports: &badPorts, + Name: "A random egress rule 2", + Action: "Accept", + Protocols: badProtos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -441,9 +466,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { { EgressRule: nil, IngressRule: &clusternetpol.ClusterNetworkPolicyIngressRule{ - Name: "A random ingress rule", - Action: "Accept", - Ports: &badPorts, + Name: "A random ingress rule", + Action: "Accept", + Protocols: badProtos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -459,9 +484,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { { IngressRule: nil, EgressRule: &clusternetpol.ClusterNetworkPolicyEgressRule{ - Name: "A random egress rule 2", - Action: "Accept", - Ports: &badPorts, + Name: "A random egress rule 2", + Action: "Accept", + Protocols: badProtos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -739,9 +764,13 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }) It("should parse a k8s ClusterNetworkPolicy with a DoesNotExist expression ", func() { - ports := []clusternetpol.ClusterNetworkPolicyPort{ + protos := []clusternetpol.ClusterNetworkPolicyProtocol{ { - PortNumber: &clusternetpol.Port{Port: 80}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, + }, }, } cnp := clusternetpol.ClusterNetworkPolicy{ @@ -764,9 +793,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Ingress: []clusternetpol.ClusterNetworkPolicyIngressRule{ { - Name: "A random ingress rule", - Action: "Accept", - Ports: &ports, + Name: "A random ingress rule", + Action: "Accept", + Protocols: protos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Pods: &clusternetpol.NamespacedPod{ @@ -813,12 +842,20 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }) It("should parse an ClusterNetworkPolicy with multiple peers and ports", func() { - ports := []clusternetpol.ClusterNetworkPolicyPort{ + protos := []clusternetpol.ClusterNetworkPolicyProtocol{ { - PortNumber: &clusternetpol.Port{Port: 80}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, + }, }, { - PortRange: &clusternetpol.PortRange{Start: 20, End: 30, Protocol: kapiv1.ProtocolUDP}, + UDP: &clusternetpol.ClusterNetworkPolicyProtocolUDP{ + DestinationPort: &clusternetpol.Port{ + Range: &clusternetpol.PortRange{Start: 20, End: 30}, + }, + }, }, } cnp := clusternetpol.ClusterNetworkPolicy{ @@ -839,9 +876,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Ingress: []clusternetpol.ClusterNetworkPolicyIngressRule{ { - Name: "A random ingress rule", - Action: "Pass", - Ports: &ports, + Name: "A random ingress rule", + Action: "Pass", + Protocols: protos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -864,9 +901,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Egress: []clusternetpol.ClusterNetworkPolicyEgressRule{ { - Name: "A random egress rule", - Action: "Deny", - Ports: &ports, + Name: "A random egress rule", + Action: "Deny", + Protocols: protos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1392,14 +1429,22 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }) It("should replace an unsupported ClusterNetworkPolicy rule with Deny action with a deny-all one", func() { - ports := []clusternetpol.ClusterNetworkPolicyPort{ + goodProtos := []clusternetpol.ClusterNetworkPolicyProtocol{ { - PortNumber: &clusternetpol.Port{Port: 80}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, + }, }, } - badPorts := []clusternetpol.ClusterNetworkPolicyPort{ + badProtos := []clusternetpol.ClusterNetworkPolicyProtocol{ { - PortRange: &clusternetpol.PortRange{Start: 40, End: 20, Protocol: kapiv1.ProtocolUDP}, + UDP: &clusternetpol.ClusterNetworkPolicyProtocolUDP{ + DestinationPort: &clusternetpol.Port{ + Range: &clusternetpol.PortRange{Start: 40, End: 20}, + }, + }, }, } cnp := clusternetpol.ClusterNetworkPolicy{ @@ -1420,9 +1465,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Ingress: []clusternetpol.ClusterNetworkPolicyIngressRule{ { - Name: "A random ingress rule", - Action: "Pass", - Ports: &badPorts, + Name: "A random ingress rule", + Action: "Pass", + Protocols: badProtos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1434,9 +1479,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, }, { - Name: "A random ingress rule 2", - Action: "Accept", - Ports: &badPorts, + Name: "A random ingress rule 2", + Action: "Accept", + Protocols: badProtos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1450,9 +1495,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Egress: []clusternetpol.ClusterNetworkPolicyEgressRule{ { - Name: "A random egress rule", - Action: "Deny", - Ports: &badPorts, + Name: "A random egress rule", + Action: "Deny", + Protocols: badProtos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1464,9 +1509,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, }, { - Name: "A random egress rule 2", - Action: "Deny", - Ports: &ports, + Name: "A random egress rule 2", + Action: "Deny", + Protocols: goodProtos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1487,9 +1532,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { { EgressRule: nil, IngressRule: &clusternetpol.ClusterNetworkPolicyIngressRule{ - Name: "A random ingress rule", - Action: "Pass", - Ports: &badPorts, + Name: "A random ingress rule", + Action: "Pass", + Protocols: badProtos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1505,9 +1550,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { { EgressRule: nil, IngressRule: &clusternetpol.ClusterNetworkPolicyIngressRule{ - Name: "A random ingress rule 2", - Action: "Accept", - Ports: &badPorts, + Name: "A random ingress rule 2", + Action: "Accept", + Protocols: badProtos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1523,9 +1568,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { { IngressRule: nil, EgressRule: &clusternetpol.ClusterNetworkPolicyEgressRule{ - Name: "A random egress rule", - Action: "Deny", - Ports: &badPorts, + Name: "A random egress rule", + Action: "Deny", + Protocols: badProtos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1730,9 +1775,13 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }) It("should parse a k8s ClusterNetworkPolicy with a Networks peer and ports", func() { - ports := []clusternetpol.ClusterNetworkPolicyPort{ + protos := []clusternetpol.ClusterNetworkPolicyProtocol{ { - PortNumber: &clusternetpol.Port{Port: 80}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, + }, }, } cnp := clusternetpol.ClusterNetworkPolicy{ @@ -1753,9 +1802,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Ingress: []clusternetpol.ClusterNetworkPolicyIngressRule{ { - Name: "A random ingress rule", - Action: "Pass", - Ports: &ports, + Name: "A random ingress rule", + Action: "Pass", + Protocols: protos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1769,9 +1818,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Egress: []clusternetpol.ClusterNetworkPolicyEgressRule{ { - Name: "A random egress rule", - Action: "Deny", - Ports: &ports, + Name: "A random egress rule", + Action: "Deny", + Protocols: protos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1835,9 +1884,13 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }) It("should parse a k8s ClusterNetworkPolicy with an invalid networks peer", func() { - ports := []clusternetpol.ClusterNetworkPolicyPort{ + protos := []clusternetpol.ClusterNetworkPolicyProtocol{ { - PortNumber: &clusternetpol.Port{Port: 80}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, + }, }, } cnp := clusternetpol.ClusterNetworkPolicy{ @@ -1858,9 +1911,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Ingress: []clusternetpol.ClusterNetworkPolicyIngressRule{ { - Name: "A random ingress rule", - Action: "Pass", - Ports: &ports, + Name: "A random ingress rule", + Action: "Pass", + Protocols: protos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1874,9 +1927,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, Egress: []clusternetpol.ClusterNetworkPolicyEgressRule{ { - Name: "A random egress rule", - Action: "Deny", - Ports: &ports, + Name: "A random egress rule", + Action: "Deny", + Protocols: protos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1900,9 +1953,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { { IngressRule: nil, EgressRule: &clusternetpol.ClusterNetworkPolicyEgressRule{ - Name: "A random egress rule", - Action: "Deny", - Ports: &ports, + Name: "A random egress rule", + Action: "Deny", + Protocols: protos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -1949,11 +2002,15 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { // cases for BANP. var _ = Describe("Test ClusterNetworkPolicy conversion - Baseline tier", func() { It("should parse a basic k8s ClusterNetworkPolicy to a GlobalNetworkPolicy", func() { - ports := []clusternetpol.ClusterNetworkPolicyPort{{ - PortNumber: &clusternetpol.Port{ - Port: 80, + protos := []clusternetpol.ClusterNetworkPolicyProtocol{ + { + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, + }, }, - }} + } bcnp := clusternetpol.ClusterNetworkPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "default", @@ -1978,9 +2035,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Baseline tier", func() }, Ingress: []clusternetpol.ClusterNetworkPolicyIngressRule{ { - Name: "The first ingress rule", - Action: "Accept", - Ports: &ports, + Name: "The first ingress rule", + Action: "Accept", + Protocols: protos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -2055,9 +2112,13 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Baseline tier", func() }) It("should parse a k8s ClusterNetworkPolicy with an invalid networks peer", func() { - ports := []clusternetpol.ClusterNetworkPolicyPort{ + protos := []clusternetpol.ClusterNetworkPolicyProtocol{ { - PortNumber: &clusternetpol.Port{Port: 80}, + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, + }, }, } cnp := clusternetpol.ClusterNetworkPolicy{ @@ -2077,8 +2138,8 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Baseline tier", func() }, Ingress: []clusternetpol.ClusterNetworkPolicyIngressRule{ { - Action: "Deny", - Ports: &ports, + Action: "Deny", + Protocols: protos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ {}, }, @@ -2086,9 +2147,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Baseline tier", func() }, Egress: []clusternetpol.ClusterNetworkPolicyEgressRule{ { - Name: "A random egress rule", - Action: "Deny", - Ports: &ports, + Name: "A random egress rule", + Action: "Deny", + Protocols: protos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ @@ -2111,8 +2172,8 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Baseline tier", func() Rules: []cerrors.ErrorClusterNetworkPolicyConversionRule{ { IngressRule: &clusternetpol.ClusterNetworkPolicyIngressRule{ - Action: "Deny", - Ports: &ports, + Action: "Deny", + Protocols: protos, From: []clusternetpol.ClusterNetworkPolicyIngressPeer{ {}, }, @@ -2121,9 +2182,9 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Baseline tier", func() }, { EgressRule: &clusternetpol.ClusterNetworkPolicyEgressRule{ - Name: "A random egress rule", - Action: "Deny", - Ports: &ports, + Name: "A random egress rule", + Action: "Deny", + Protocols: protos, To: []clusternetpol.ClusterNetworkPolicyEgressPeer{ { Namespaces: &metav1.LabelSelector{ diff --git a/libcalico-go/lib/backend/syncersv1/updateprocessors/globalnetworkpolicyprocessor_test.go b/libcalico-go/lib/backend/syncersv1/updateprocessors/globalnetworkpolicyprocessor_test.go index 5db23df7fa2..44cfe715912 100644 --- a/libcalico-go/lib/backend/syncersv1/updateprocessors/globalnetworkpolicyprocessor_test.go +++ b/libcalico-go/lib/backend/syncersv1/updateprocessors/globalnetworkpolicyprocessor_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2025 Tigera, Inc. All rights reserved. +// Copyright (c) 2017-2026 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -308,15 +308,19 @@ var _ = Describe("Test the GlobalNetworkPolicy update processor", func() { // Define ClusterNetworkPolicies and the corresponding expected v1 KVPairs. // -// kcnp1 is a k8s ClusterNetworkPolicy with a single Egress rule, which contains ports only, +// kcnp1 is a k8s ClusterNetworkPolicy with a single Egress rule, which contains protocols only, // and no selectors. var ( kcnpOrder = float64(1000.0) - ports = []clusternetpol.ClusterNetworkPolicyPort{{ - PortNumber: &clusternetpol.Port{ - Port: 80, + protos = []clusternetpol.ClusterNetworkPolicyProtocol{ + { + TCP: &clusternetpol.ClusterNetworkPolicyProtocolTCP{ + DestinationPort: &clusternetpol.Port{ + Number: 80, + }, + }, }, - }} + } kcnp1 = clusternetpol.ClusterNetworkPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "test.policy", @@ -336,7 +340,7 @@ var ( Namespaces: &metav1.LabelSelector{}, }, }, - Ports: &ports, + Protocols: protos, }, }, }, From 394ff5e3630d5d189398ebd5a8bae7d81c2a93b7 Mon Sep 17 00:00:00 2001 From: Mazdak Nasab Date: Mon, 9 Feb 2026 14:56:03 -0800 Subject: [PATCH 2/7] return early --- .../lib/backend/k8s/conversion/clusternetworkpolicy.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go index 92ec9ca9f8f..d783c8eb942 100644 --- a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go +++ b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go @@ -377,18 +377,21 @@ func k8sCNPPortToCalicoFields(cnpProto *clusternetpol.ClusterNetworkPolicyProtoc dstPort, err = k8sCNPPortToCalico(cnpProto.TCP.DestinationPort) p := numorstring.ProtocolFromString(numorstring.ProtocolTCP) protocol = &p + return } if cnpProto.UDP != nil { dstPort, err = k8sCNPPortToCalico(cnpProto.UDP.DestinationPort) p := numorstring.ProtocolFromString(numorstring.ProtocolUDP) protocol = &p + return } if cnpProto.SCTP != nil { dstPort, err = k8sCNPPortToCalico(cnpProto.SCTP.DestinationPort) p := numorstring.ProtocolFromString(numorstring.ProtocolSCTP) protocol = &p + return } return From d642887ab799ac68dfc553b705ff4652112f4d74 Mon Sep 17 00:00:00 2001 From: Mazdak Nasab Date: Mon, 9 Feb 2026 15:07:10 -0800 Subject: [PATCH 3/7] make generate --- apiserver/deps.txt | 2 +- app-policy/deps.txt | 2 +- calicoctl/deps.txt | 2 +- cni-plugin/deps.txt | 2 +- confd/deps.txt | 2 +- e2e/deps.txt | 2 +- felix/deps.txt | 2 +- hack/deps.txt | 2 +- kube-controllers/deps.txt | 2 +- libcalico-go/deps.txt | 2 +- node/deps.txt | 2 +- typha/deps.txt | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apiserver/deps.txt b/apiserver/deps.txt index e0793dcd19f..805f458a21b 100644 --- a/apiserver/deps.txt +++ b/apiserver/deps.txt @@ -112,7 +112,7 @@ k8s.io/kubernetes v1.34.3 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 diff --git a/app-policy/deps.txt b/app-policy/deps.txt index a0b0699a7b9..449ccedc0f1 100644 --- a/app-policy/deps.txt +++ b/app-policy/deps.txt @@ -110,7 +110,7 @@ k8s.io/kubernetes v1.34.3 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 sigs.k8s.io/knftables v0.0.19 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 diff --git a/calicoctl/deps.txt b/calicoctl/deps.txt index 99a2f7fba71..90d810c0581 100644 --- a/calicoctl/deps.txt +++ b/calicoctl/deps.txt @@ -83,7 +83,7 @@ k8s.io/klog/v2 v2.130.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 diff --git a/cni-plugin/deps.txt b/cni-plugin/deps.txt index 9b950f88a75..a797887348c 100644 --- a/cni-plugin/deps.txt +++ b/cni-plugin/deps.txt @@ -96,7 +96,7 @@ k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 sigs.k8s.io/knftables v0.0.19 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 diff --git a/confd/deps.txt b/confd/deps.txt index 4db4d945d19..b7d95d006e9 100644 --- a/confd/deps.txt +++ b/confd/deps.txt @@ -79,7 +79,7 @@ k8s.io/klog/v2 v2.130.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 diff --git a/e2e/deps.txt b/e2e/deps.txt index e1c9c5cda19..c31481cbd1c 100644 --- a/e2e/deps.txt +++ b/e2e/deps.txt @@ -117,7 +117,7 @@ k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 sigs.k8s.io/controller-runtime v0.22.3 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 diff --git a/felix/deps.txt b/felix/deps.txt index 2a6e2f887a9..3cff864537d 100644 --- a/felix/deps.txt +++ b/felix/deps.txt @@ -150,7 +150,7 @@ k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 modernc.org/memory v1.11.0 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 sigs.k8s.io/knftables v0.0.19 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 diff --git a/hack/deps.txt b/hack/deps.txt index 57a2d137793..fb2f60c76f6 100644 --- a/hack/deps.txt +++ b/hack/deps.txt @@ -81,7 +81,7 @@ k8s.io/klog/v2 v2.130.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 diff --git a/kube-controllers/deps.txt b/kube-controllers/deps.txt index 4e0c6abd86a..b48f36b922c 100644 --- a/kube-controllers/deps.txt +++ b/kube-controllers/deps.txt @@ -123,7 +123,7 @@ k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 sigs.k8s.io/controller-runtime v0.22.3 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 sigs.k8s.io/knftables v0.0.19 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 diff --git a/libcalico-go/deps.txt b/libcalico-go/deps.txt index 367acbc72a0..d8020ce04cc 100644 --- a/libcalico-go/deps.txt +++ b/libcalico-go/deps.txt @@ -94,7 +94,7 @@ k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 sigs.k8s.io/controller-runtime v0.22.3 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 sigs.k8s.io/kind v0.30.0 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 diff --git a/node/deps.txt b/node/deps.txt index 2b37d1030ac..90ea5f8ffea 100644 --- a/node/deps.txt +++ b/node/deps.txt @@ -151,7 +151,7 @@ k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 modernc.org/memory v1.11.0 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 sigs.k8s.io/knftables v0.0.19 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 diff --git a/typha/deps.txt b/typha/deps.txt index 972de9e0f1a..10994e2a68c 100644 --- a/typha/deps.txt +++ b/typha/deps.txt @@ -84,7 +84,7 @@ k8s.io/klog/v2 v2.130.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 -sigs.k8s.io/network-policy-api v0.1.8-0.20251216172012-399040aaf83d +sigs.k8s.io/network-policy-api v0.1.8-0.20260205105847-196cf8e0d449 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 From a5cb6599b1068c2c3b6f6e0c4f098d6526199e3a Mon Sep 17 00:00:00 2001 From: Mazdak Nasab Date: Mon, 9 Feb 2026 15:10:20 -0800 Subject: [PATCH 4/7] check if port is nil --- .../lib/backend/k8s/conversion/clusternetworkpolicy.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go index d783c8eb942..918a2a55b6b 100644 --- a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go +++ b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go @@ -399,6 +399,9 @@ func k8sCNPPortToCalicoFields(cnpProto *clusternetpol.ClusterNetworkPolicyProtoc func k8sCNPPortToCalico(port *clusternetpol.Port) (*numorstring.Port, error) { // Only one of the Number or Range is set. + if port == nil { + return nil, nil + } if port.Number != 0 { p := numorstring.SinglePort(uint16(port.Number)) return &p, nil From 3d96bcde09e0272a4c2b081fa1382bc21cb53b66 Mon Sep 17 00:00:00 2001 From: Mazdak Nasab Date: Mon, 9 Feb 2026 15:17:45 -0800 Subject: [PATCH 5/7] update error message --- libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go index 918a2a55b6b..c73eef0c1ba 100644 --- a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go +++ b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go @@ -332,7 +332,7 @@ func unpackCNPProtocols(cnpProtocols []clusternetpol.ClusterNetworkPolicyProtoco for _, p := range protocols { protocol, calicoPort, err := k8sCNPPortToCalicoFields(&p) if err != nil { - return nil, nil, fmt.Errorf("failed to parse k8s port: %s", err) + return nil, nil, fmt.Errorf("failed to parse k8s protocol: %s", err) } if protocol == nil && calicoPort == nil { From 44b4e84f9339bd272cb4f87349c452cc87c572ee Mon Sep 17 00:00:00 2001 From: Mazdak Nasab Date: Mon, 9 Feb 2026 15:55:56 -0800 Subject: [PATCH 6/7] fix ut --- .../k8s/conversion/clusternetworkpolicy_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy_test.go b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy_test.go index 32747fb14ae..6e809471207 100644 --- a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy_test.go +++ b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy_test.go @@ -479,7 +479,7 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, }, }, - Reason: "k8s rule couldn't be converted: failed to parse k8s port: minimum port number (1000) is greater than maximum port number (10) in port range", + Reason: "k8s rule couldn't be converted: failed to parse k8s protocol: minimum port number (1000) is greater than maximum port number (10) in port range", }, { IngressRule: nil, @@ -497,7 +497,7 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, }, }, - Reason: "k8s rule couldn't be converted: failed to parse k8s port: minimum port number (1000) is greater than maximum port number (10) in port range", + Reason: "k8s rule couldn't be converted: failed to parse k8s protocol: minimum port number (1000) is greater than maximum port number (10) in port range", }, }, } @@ -1545,7 +1545,7 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, }, }, - Reason: "k8s rule couldn't be converted: failed to parse k8s port: minimum port number (40) is greater than maximum port number (20) in port range", + Reason: "k8s rule couldn't be converted: failed to parse k8s protocol: minimum port number (40) is greater than maximum port number (20) in port range", }, { EgressRule: nil, @@ -1563,7 +1563,7 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, }, }, - Reason: "k8s rule couldn't be converted: failed to parse k8s port: minimum port number (40) is greater than maximum port number (20) in port range", + Reason: "k8s rule couldn't be converted: failed to parse k8s protocol: minimum port number (40) is greater than maximum port number (20) in port range", }, { IngressRule: nil, @@ -1581,7 +1581,7 @@ var _ = Describe("Test ClusterNetworkPolicy conversion - Admin tier", func() { }, }, }, - Reason: "k8s rule couldn't be converted: failed to parse k8s port: minimum port number (40) is greater than maximum port number (20) in port range", + Reason: "k8s rule couldn't be converted: failed to parse k8s protocol: minimum port number (40) is greater than maximum port number (20) in port range", }, }, } From 8bca11554bba599636ffde4fd2feaed037071010 Mon Sep 17 00:00:00 2001 From: Mazdak Nasab Date: Tue, 10 Feb 2026 11:08:12 -0800 Subject: [PATCH 7/7] return error for named ports --- .../lib/backend/k8s/conversion/clusternetworkpolicy.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go index c73eef0c1ba..8f92aae9c55 100644 --- a/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go +++ b/libcalico-go/lib/backend/k8s/conversion/clusternetworkpolicy.go @@ -394,6 +394,12 @@ func k8sCNPPortToCalicoFields(cnpProto *clusternetpol.ClusterNetworkPolicyProtoc return } + // TODO: Add support for NamedPorts + if len(cnpProto.DestinationNamedPort) != 0 { + err = fmt.Errorf("named ports are not supported yet.") + return + } + return }