Skip to content

Commit 7609a70

Browse files
committed
cni result enhancement
Signed-off-by: DrAuYueng <[email protected]>
1 parent 1cf3b58 commit 7609a70

File tree

4 files changed

+259
-8
lines changed

4 files changed

+259
-8
lines changed

cni-plugin/pkg/k8s/k8s.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -532,12 +532,21 @@ func CmdAddK8s(ctx context.Context, args *skel.CmdArgs, conf types.NetConf, epID
532532
logger.Info("Wrote updated endpoint to datastore")
533533

534534
// Add the interface created above to the CNI result.
535-
result.Interfaces = append(result.Interfaces, &cniv1.Interface{
536-
Name: endpoint.Spec.InterfaceName,
537-
Mac: endpoint.Spec.MAC,
535+
hostInterface := &cniv1.Interface{
536+
Name: hostVethName,
537+
}
538+
contInterface := &cniv1.Interface{
539+
Name: args.IfName,
540+
Mac: contVethMac,
538541
Mtu: conf.MTU,
539542
Sandbox: args.Netns,
540-
})
543+
}
544+
545+
result.Interfaces = append(result.Interfaces, hostInterface, contInterface)
546+
547+
for _, ip := range result.IPs {
548+
ip.Interface = cniv1.Int(1)
549+
}
541550

542551
// Conditionally wait for host-local Felix to program the policy for this WEP.
543552
// Error if negative, ignore if 0.

cni-plugin/pkg/plugin/plugin.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,12 +508,21 @@ func cmdAdd(args *skel.CmdArgs) (err error) {
508508
logger.WithField("endpoint", endpoint).Info("Wrote endpoint to datastore")
509509

510510
// Add the interface created above to the CNI result.
511-
result.Interfaces = append(result.Interfaces, &cniv1.Interface{
512-
Name: endpoint.Spec.InterfaceName,
511+
hostInterface := &cniv1.Interface{
512+
Name: endpoint.Spec.InterfaceName,
513+
}
514+
contInterface := &cniv1.Interface{
515+
Name: args.IfName,
513516
Mac: endpoint.Spec.MAC,
514517
Mtu: conf.MTU,
515518
Sandbox: args.Netns,
516-
})
519+
}
520+
521+
result.Interfaces = append(result.Interfaces, hostInterface, contInterface)
522+
523+
for _, ip := range result.IPs {
524+
ip.Interface = cniv1.Int(1)
525+
}
517526
}
518527

519528
// Handle profile creation - this is only done if there isn't a specific policy handler.

cni-plugin/tests/calico_cni_k8s_test.go

Lines changed: 176 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
cniv1 "github.com/containernetworking/cni/pkg/types/100"
2222
"github.com/containernetworking/plugins/pkg/ns"
2323
cnitestutils "github.com/containernetworking/plugins/pkg/testutils"
24+
"github.com/mcuadros/go-version"
2425
. "github.com/onsi/ginkgo"
2526
. "github.com/onsi/gomega"
2627
api "github.com/projectcalico/api/pkg/apis/projectcalico/v3"
@@ -2581,7 +2582,9 @@ var _ = Describe("Kubernetes CNI tests", func() {
25812582
// The MAC address will be different, since we create a new veth.
25822583
Expect(len(resultSecondAdd.Interfaces)).Should(Equal(len(result.Interfaces)))
25832584
for i := range resultSecondAdd.Interfaces {
2584-
Expect(resultSecondAdd.Interfaces[i].Mac).ShouldNot(Equal(result.Interfaces[i].Mac))
2585+
if resultSecondAdd.Interfaces[i].Mac != "" {
2586+
Expect(resultSecondAdd.Interfaces[i].Mac).ShouldNot(Equal(result.Interfaces[i].Mac))
2587+
}
25852588
resultSecondAdd.Interfaces[i].Mac = ""
25862589
result.Interfaces[i].Mac = ""
25872590
}
@@ -3396,6 +3399,178 @@ var _ = Describe("Kubernetes CNI tests", func() {
33963399
Expect(err).To(HaveOccurred())
33973400
})
33983401
})
3402+
3403+
Context("When CNI ADD success, return all interfaces", func() {
3404+
var nc types.NetConf
3405+
var netconf string
3406+
var ipPool4CIDR *net.IPNet
3407+
var ipPool6CIDR *net.IPNet
3408+
var ipPool4 = "50.80.0.0/16"
3409+
var ipPool6 = "fd80:50::/96"
3410+
var clientset *kubernetes.Clientset
3411+
var testNS = testutils.K8S_TEST_NS
3412+
3413+
BeforeEach(func() {
3414+
if version.Compare(cniVersion, "0.3.0", "<") {
3415+
Skip("Skipping test because of CNI version < 0.3.0")
3416+
}
3417+
// Build the network config for this set of tests.
3418+
nc = types.NetConf{
3419+
CNIVersion: cniVersion,
3420+
Name: "calico-uts",
3421+
Type: "calico",
3422+
EtcdEndpoints: fmt.Sprintf("http://%s:2379", os.Getenv("ETCD_IP")),
3423+
DatastoreType: os.Getenv("DATASTORE_TYPE"),
3424+
Kubernetes: types.Kubernetes{Kubeconfig: "/home/user/certs/kubeconfig"},
3425+
Policy: types.Policy{PolicyType: "k8s"},
3426+
NodenameFileOptional: true,
3427+
LogLevel: "debug",
3428+
Nodename: testNodeName,
3429+
}
3430+
nc.IPAM.Type = "calico-ipam"
3431+
ncb, err := json.Marshal(nc)
3432+
Expect(err).NotTo(HaveOccurred())
3433+
netconf = string(ncb)
3434+
3435+
// Create clients.
3436+
clientset = getKubernetesClient()
3437+
3438+
// Make sure the namespace exists.
3439+
ensureNamespace(clientset, testutils.K8S_TEST_NS)
3440+
3441+
_, ipPool4CIDR, err = net.ParseCIDR(ipPool4)
3442+
Expect(err).NotTo(HaveOccurred())
3443+
3444+
_, ipPool6CIDR, err = net.ParseCIDR(ipPool6)
3445+
Expect(err).NotTo(HaveOccurred())
3446+
3447+
// Create a new IP Pool.
3448+
testutils.MustCreateNewIPPool(calicoClient, ipPool4, false, false, true)
3449+
testutils.MustCreateNewIPPool(calicoClient, ipPool6, false, false, true)
3450+
3451+
})
3452+
3453+
AfterEach(func() {
3454+
// Delete pod
3455+
ensurePodDeleted(clientset, testNS, testPodName)
3456+
3457+
// Delete the IP Pool.
3458+
testutils.MustDeleteIPPool(calicoClient, ipPool4)
3459+
testutils.MustDeleteIPPool(calicoClient, ipPool6)
3460+
})
3461+
3462+
It("should allocate IPv4 only", func() {
3463+
// Now create a K8s pod passing in an IP pool.
3464+
ensurePodCreated(clientset, testNS, &v1.Pod{
3465+
ObjectMeta: metav1.ObjectMeta{
3466+
Name: testPodName,
3467+
Annotations: map[string]string{
3468+
"cni.projectcalico.org/ipv4pools": "[\"50.80.0.0/16\"]",
3469+
},
3470+
},
3471+
Spec: v1.PodSpec{
3472+
Containers: []v1.Container{{
3473+
Name: testPodName,
3474+
Image: "ignore",
3475+
}},
3476+
NodeName: testNodeName,
3477+
},
3478+
})
3479+
3480+
// Run the CNI plugin.
3481+
_, result, _, contAddresses, _, contNs, err := testutils.CreateContainer(netconf, testPodName, testNS, "")
3482+
Expect(err).NotTo(HaveOccurred())
3483+
3484+
Expect(len(contAddresses)).Should(Equal(1))
3485+
3486+
for _, ip := range contAddresses {
3487+
podIP := ip.IP
3488+
if podIP.To4() != nil {
3489+
Expect(ipPool4CIDR.Contains(podIP)).Should(BeTrue())
3490+
} else {
3491+
Expect(ipPool6CIDR.Contains(podIP)).Should(BeTrue())
3492+
}
3493+
}
3494+
3495+
interfaces := result.Interfaces
3496+
3497+
Expect(len(interfaces)).Should(Equal(2))
3498+
Expect(len(result.IPs)).Should(Equal(1))
3499+
3500+
for _, ip := range result.IPs {
3501+
interfaceIndex := ip.Interface
3502+
Expect(interfaceIndex).ShouldNot(BeNil())
3503+
iface := interfaces[*interfaceIndex]
3504+
Expect(iface).ShouldNot(BeNil())
3505+
Expect(iface.Name).Should(Equal("eth0"))
3506+
Expect(iface.Mac).ShouldNot(BeEmpty())
3507+
Expect(iface.Sandbox).ShouldNot(BeEmpty())
3508+
}
3509+
3510+
// Delete the container.
3511+
_, err = testutils.DeleteContainer(netconf, contNs.Path(), testPodName, testNS)
3512+
Expect(err).ShouldNot(HaveOccurred())
3513+
})
3514+
3515+
It("should allocate IPv4 and IPv6 addresses and handle dual stack", func() {
3516+
// Now create a K8s pod passing in an IP pool.
3517+
ensurePodCreated(clientset, testNS, &v1.Pod{
3518+
ObjectMeta: metav1.ObjectMeta{
3519+
Name: testPodName,
3520+
Annotations: map[string]string{
3521+
"cni.projectcalico.org/ipv4pools": "[\"50.80.0.0/16\"]",
3522+
"cni.projectcalico.org/ipv6pools": "[\"fd80:50::/96\"]",
3523+
},
3524+
},
3525+
Spec: v1.PodSpec{
3526+
Containers: []v1.Container{{
3527+
Name: testPodName,
3528+
Image: "ignore",
3529+
}},
3530+
NodeName: testNodeName,
3531+
},
3532+
})
3533+
assignIpv6 := "true"
3534+
nc.IPAM.AssignIpv6 = &assignIpv6
3535+
ncb, err := json.Marshal(nc)
3536+
Expect(err).NotTo(HaveOccurred())
3537+
netconf = string(ncb)
3538+
3539+
// Run the CNI plugin.
3540+
_, result, _, contAddresses, _, contNs, err := testutils.CreateContainer(netconf, testPodName, testNS, "")
3541+
Expect(err).NotTo(HaveOccurred())
3542+
3543+
Expect(len(contAddresses)).Should(Equal(2))
3544+
3545+
for _, ip := range contAddresses {
3546+
podIP := ip.IP
3547+
if podIP.To4() != nil {
3548+
Expect(ipPool4CIDR.Contains(podIP)).Should(BeTrue())
3549+
} else {
3550+
Expect(ipPool6CIDR.Contains(podIP)).Should(BeTrue())
3551+
}
3552+
}
3553+
3554+
interfaces := result.Interfaces
3555+
3556+
Expect(len(interfaces)).Should(Equal(2))
3557+
Expect(len(result.IPs)).Should(Equal(2))
3558+
3559+
for _, ip := range result.IPs {
3560+
interfaceIndex := ip.Interface
3561+
Expect(interfaceIndex).ShouldNot(BeNil())
3562+
iface := interfaces[*interfaceIndex]
3563+
Expect(iface).ShouldNot(BeNil())
3564+
Expect(iface.Name).Should(Equal("eth0"))
3565+
Expect(iface.Mac).ShouldNot(BeEmpty())
3566+
Expect(iface.Sandbox).ShouldNot(BeEmpty())
3567+
}
3568+
3569+
// Delete the container.
3570+
_, err = testutils.DeleteContainer(netconf, contNs.Path(), testPodName, testNS)
3571+
Expect(err).ShouldNot(HaveOccurred())
3572+
})
3573+
})
33993574
})
34003575

34013576
func checkPodIPAnnotations(clientset *kubernetes.Clientset, ns, name, expectedIP, expectedIPs string) {

cni-plugin/tests/calico_cni_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
cniv1 "github.com/containernetworking/cni/pkg/types/100"
1717
"github.com/containernetworking/plugins/pkg/ns"
18+
"github.com/mcuadros/go-version"
1819
. "github.com/onsi/ginkgo"
1920
. "github.com/onsi/gomega"
2021
apiv3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3"
@@ -935,6 +936,63 @@ var _ = Describe("CalicoCni", func() {
935936
}, 10)
936937

937938
})
939+
940+
Context("When CNI ADD success, return all interfaces", func() {
941+
ipPool4 := "10.0.0.0/8"
942+
netconf := fmt.Sprintf(`
943+
{
944+
"cniVersion": "%s",
945+
"name": "net1",
946+
"type": "calico",
947+
"etcd_endpoints": "http://%s:2379",
948+
"nodename_file_optional": true,
949+
"datastore_type": "%s",
950+
"ipam": {
951+
"type": "host-local",
952+
"subnet": "%s"
953+
}
954+
}`, cniVersion, os.Getenv("ETCD_IP"), os.Getenv("DATASTORE_TYPE"), ipPool4)
955+
956+
BeforeEach(func() {
957+
if version.Compare(cniVersion, "0.3.0", "<") {
958+
Skip("Skipping test because of CNI version < 0.3.0")
959+
}
960+
})
961+
962+
It("should allocate IPv4 only", func() {
963+
_, ipPool4CIDR, err := net.ParseCIDR(ipPool4)
964+
Expect(err).NotTo(HaveOccurred())
965+
966+
_, result, _, contAddresses, _, contNs, err := testutils.CreateContainer(netconf, "", testutils.TEST_DEFAULT_NS, "")
967+
Expect(err).ShouldNot(HaveOccurred())
968+
969+
Expect(len(contAddresses)).Should(Equal(1))
970+
971+
for _, ip := range contAddresses {
972+
podIP := ip.IP
973+
Expect(ipPool4CIDR.Contains(podIP)).Should(BeTrue())
974+
}
975+
976+
interfaces := result.Interfaces
977+
978+
Expect(len(interfaces)).Should(Equal(2))
979+
Expect(len(result.IPs)).Should(Equal(1))
980+
981+
for _, ip := range result.IPs {
982+
interfaceIndex := ip.Interface
983+
Expect(interfaceIndex).ShouldNot(BeNil())
984+
iface := interfaces[*interfaceIndex]
985+
Expect(iface).ShouldNot(BeNil())
986+
Expect(iface.Name).Should(Equal("eth0"))
987+
Expect(iface.Mac).ShouldNot(BeEmpty())
988+
Expect(iface.Sandbox).ShouldNot(BeEmpty())
989+
}
990+
991+
// Delete the container.
992+
_, err = testutils.DeleteContainer(netconf, contNs.Path(), "", testutils.TEST_DEFAULT_NS)
993+
Expect(err).ShouldNot(HaveOccurred())
994+
})
995+
})
938996
})
939997

940998
func netlinkDefaultCIDR() *net.IPNet {

0 commit comments

Comments
 (0)