From 517f0e488e26c0f8a44539cd3ebc784f5374fe4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=A5=96=E5=BB=BA?= Date: Tue, 17 Dec 2024 16:09:56 +0800 Subject: [PATCH] e2e: add test case for specifying mac address when nad plugin is macvlan (#4836) Signed-off-by: zhangzujian --- dist/images/kubectl-ko | 4 +- pkg/controller/gc.go | 4 +- pkg/controller/pod.go | 10 +- pkg/controller/service_lb.go | 8 +- pkg/controller/vpc_dns.go | 3 +- pkg/controller/vpc_egress_gateway.go | 3 +- pkg/controller/vpc_lb.go | 7 +- pkg/controller/vpc_nat_gateway.go | 11 +- pkg/daemon/controller.go | 3 +- pkg/daemon/controller_linux.go | 3 +- pkg/daemon/controller_windows.go | 3 +- pkg/util/const.go | 1 - pkg/util/k8s.go | 19 +- pkg/util/network_attachment.go | 127 +-------- pkg/util/network_attachment_test.go | 332 +----------------------- test/e2e/framework/cni.go | 5 +- test/e2e/kube-ovn/node/node.go | 8 +- test/e2e/kube-ovn/pod/pod_routes.go | 4 +- test/e2e/kube-ovn/service/service.go | 2 +- test/e2e/kube-ovn/subnet/subnet.go | 8 +- test/e2e/lb-svc/e2e_test.go | 4 +- test/e2e/multus/e2e_test.go | 83 +++++- test/e2e/ovn-vpc-nat-gw/e2e_test.go | 8 +- test/e2e/vip/e2e_test.go | 2 +- test/e2e/vpc-egress-gateway/e2e_test.go | 3 +- test/e2e/webhook/pod/pod.go | 2 +- 26 files changed, 150 insertions(+), 517 deletions(-) diff --git a/dist/images/kubectl-ko b/dist/images/kubectl-ko index bef1de8a5c8..03dadcc5646 100755 --- a/dist/images/kubectl-ko +++ b/dist/images/kubectl-ko @@ -1247,7 +1247,7 @@ spec: - name: $podName image: $imageID imagePullPolicy: IfNotPresent - command: ["sh", "-c", "sleep infinity"] + command: ["sleep", "infinity"] nodeSelector: kubernetes.io/hostname: $nodeID EOF @@ -1271,7 +1271,7 @@ spec: - name: $podName image: $imageID imagePullPolicy: IfNotPresent - command: ["sh", "-c", "sleep infinity"] + command: ["sleep", "infinity"] nodeSelector: kubernetes.io/hostname: $nodeID EOF diff --git a/pkg/controller/gc.go b/pkg/controller/gc.go index c017d163c99..01d48511198 100644 --- a/pkg/controller/gc.go +++ b/pkg/controller/gc.go @@ -7,6 +7,8 @@ import ( "strings" "unicode" + nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + nadutils "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/utils" "github.com/ovn-org/libovsdb/ovsdb" "github.com/scylladb/go-set/strset" corev1 "k8s.io/api/core/v1" @@ -963,7 +965,7 @@ func (c *Controller) getVMLsps() []string { vmLsp := ovs.PodNameToPortName(vm.Name, ns.Name, util.OvnProvider) vmLsps = append(vmLsps, vmLsp) - attachNets, err := util.ParsePodNetworkAnnotation(vm.Spec.Template.ObjectMeta.Annotations[util.AttachmentNetworkAnnotation], vm.Namespace) + attachNets, err := nadutils.ParseNetworkAnnotation(vm.Spec.Template.ObjectMeta.Annotations[nadv1.NetworkAttachmentAnnot], vm.Namespace) if err != nil { klog.Errorf("failed to get attachment subnet of vm %s, %v", vm.Name, err) continue diff --git a/pkg/controller/pod.go b/pkg/controller/pod.go index 42ed9191c4a..542bdfa34d5 100644 --- a/pkg/controller/pod.go +++ b/pkg/controller/pod.go @@ -13,6 +13,8 @@ import ( "sync" "time" + nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + nadutils "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/utils" "github.com/scylladb/go-set/strset" "gopkg.in/k8snetworkplumbingwg/multus-cni.v4/pkg/logging" multustypes "gopkg.in/k8snetworkplumbingwg/multus-cni.v4/pkg/types" @@ -1466,10 +1468,10 @@ type kubeovnNet struct { } func (c *Controller) getPodAttachmentNet(pod *v1.Pod) ([]*kubeovnNet, error) { - var multusNets []*multustypes.NetworkSelectionElement + var multusNets []*nadv1.NetworkSelectionElement defaultAttachNetworks := pod.Annotations[util.DefaultNetworkAnnotation] if defaultAttachNetworks != "" { - attachments, err := util.ParsePodNetworkAnnotation(defaultAttachNetworks, pod.Namespace) + attachments, err := nadutils.ParseNetworkAnnotation(defaultAttachNetworks, pod.Namespace) if err != nil { klog.Errorf("failed to parse default attach net for pod '%s', %v", pod.Name, err) return nil, err @@ -1477,9 +1479,9 @@ func (c *Controller) getPodAttachmentNet(pod *v1.Pod) ([]*kubeovnNet, error) { multusNets = attachments } - attachNetworks := pod.Annotations[util.AttachmentNetworkAnnotation] + attachNetworks := pod.Annotations[nadv1.NetworkAttachmentAnnot] if attachNetworks != "" { - attachments, err := util.ParsePodNetworkAnnotation(attachNetworks, pod.Namespace) + attachments, err := nadutils.ParseNetworkAnnotation(attachNetworks, pod.Namespace) if err != nil { klog.Errorf("failed to parse attach net for pod '%s', %v", pod.Name, err) return nil, err diff --git a/pkg/controller/service_lb.go b/pkg/controller/service_lb.go index 24a88b53d8b..b0c2cd0ab36 100644 --- a/pkg/controller/service_lb.go +++ b/pkg/controller/service_lb.go @@ -83,8 +83,8 @@ func (c *Controller) genLbSvcDeployment(svc *corev1.Service, nad *nadv1.NetworkA attachSubnetAnnotation := fmt.Sprintf(util.LogicalSwitchAnnotationTemplate, providerName) attachIPAnnotation := fmt.Sprintf(util.IPAddressAnnotationTemplate, providerName) podAnnotations := map[string]string{ - util.AttachmentNetworkAnnotation: fmt.Sprintf("%s/%s", attachmentNs, attachmentName), - attachSubnetAnnotation: svc.Annotations[attachSubnetAnnotation], + nadv1.NetworkAttachmentAnnot: fmt.Sprintf("%s/%s", attachmentNs, attachmentName), + attachSubnetAnnotation: svc.Annotations[attachSubnetAnnotation], } if svc.Spec.LoadBalancerIP != "" { podAnnotations[attachIPAnnotation] = svc.Spec.LoadBalancerIP @@ -146,8 +146,8 @@ func (c *Controller) updateLbSvcDeployment(svc *corev1.Service, dp *v1.Deploymen attachSubnetAnnotation := fmt.Sprintf(util.LogicalSwitchAnnotationTemplate, providerName) attachIPAnnotation := fmt.Sprintf(util.IPAddressAnnotationTemplate, providerName) podAnnotations := map[string]string{ - util.AttachmentNetworkAnnotation: fmt.Sprintf("%s/%s", attachmentNs, attachmentName), - attachSubnetAnnotation: svc.Annotations[attachSubnetAnnotation], + nadv1.NetworkAttachmentAnnot: fmt.Sprintf("%s/%s", attachmentNs, attachmentName), + attachSubnetAnnotation: svc.Annotations[attachSubnetAnnotation], } if svc.Spec.LoadBalancerIP != "" { podAnnotations[attachIPAnnotation] = svc.Spec.LoadBalancerIP diff --git a/pkg/controller/vpc_dns.go b/pkg/controller/vpc_dns.go index de086f3f4bc..e8b07f86687 100644 --- a/pkg/controller/vpc_dns.go +++ b/pkg/controller/vpc_dns.go @@ -13,6 +13,7 @@ import ( "strings" "text/template" + nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" v1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" @@ -371,7 +372,7 @@ func (c *Controller) genVpcDNSSlr(vpcName, namespace string) (*kubeovnv1.SwitchL func setVpcDNSInterface(dp *v1.Deployment, subnetName string, defaultSubnet *kubeovnv1.Subnet) { annotations := dp.Spec.Template.Annotations annotations[util.LogicalSwitchAnnotation] = subnetName - annotations[util.AttachmentNetworkAnnotation] = fmt.Sprintf("%s/%s", corev1.NamespaceDefault, nadName) + annotations[nadv1.NetworkAttachmentAnnot] = fmt.Sprintf("%s/%s", corev1.NamespaceDefault, nadName) annotations[fmt.Sprintf(util.LogicalSwitchAnnotationTemplate, nadProvider)] = util.DefaultSubnet setVpcDNSRoute(dp, defaultSubnet.Spec.Gateway) diff --git a/pkg/controller/vpc_egress_gateway.go b/pkg/controller/vpc_egress_gateway.go index e7c1a326248..1ad6407006a 100644 --- a/pkg/controller/vpc_egress_gateway.go +++ b/pkg/controller/vpc_egress_gateway.go @@ -10,6 +10,7 @@ import ( "strconv" "strings" + nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" @@ -314,7 +315,7 @@ func (c *Controller) reconcileVpcEgressGatewayWorkload(gw *kubeovnv1.VpcEgressGa klog.Error(err) return attachmentNetworkName, nil, nil, nil, err } - annotations[util.AttachmentNetworkAnnotation] = attachmentNetworkName + annotations[nadv1.NetworkAttachmentAnnot] = attachmentNetworkName annotations[util.LogicalSwitchAnnotation] = intSubnet.Name if len(gw.Spec.InternalIPs) != 0 { // set internal IPs diff --git a/pkg/controller/vpc_lb.go b/pkg/controller/vpc_lb.go index 1dad4856b5e..57c8e241edd 100644 --- a/pkg/controller/vpc_lb.go +++ b/pkg/controller/vpc_lb.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" v1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" @@ -103,9 +104,9 @@ func (c *Controller) genVpcLbDeployment(vpc *kubeovnv1.Vpc) (*v1.Deployment, err } podAnnotations := map[string]string{ - util.VpcAnnotation: vpc.Name, - util.LogicalSwitchAnnotation: defaultSubnet.Name, - util.AttachmentNetworkAnnotation: fmt.Sprintf(`[{"name": "%s", "default-route": ["%s"]}]`, util.VpcLbNetworkAttachment, strings.ReplaceAll(gateway, ",", `" ,"`)), + util.VpcAnnotation: vpc.Name, + util.LogicalSwitchAnnotation: defaultSubnet.Name, + nadv1.NetworkAttachmentAnnot: fmt.Sprintf(`[{"name": "%s", "default-route": ["%s"]}]`, util.VpcLbNetworkAttachment, strings.ReplaceAll(gateway, ",", `" ,"`)), } deployment := &v1.Deployment{ diff --git a/pkg/controller/vpc_nat_gateway.go b/pkg/controller/vpc_nat_gateway.go index 7621d19bf69..ea83614b7f0 100644 --- a/pkg/controller/vpc_nat_gateway.go +++ b/pkg/controller/vpc_nat_gateway.go @@ -13,6 +13,7 @@ import ( "strings" "time" + nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" v1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" @@ -696,7 +697,7 @@ func (c *Controller) setNatGwAPIAccess(annotations map[string]string, externalNe // Attach the NADs to the Pod by adding them to the special annotation attachmentAnnotation := fmt.Sprintf("%s, %s", externalNetworkAttachment, apiNetworkAttachment) - annotations[util.AttachmentNetworkAnnotation] = attachmentAnnotation + annotations[nadv1.NetworkAttachmentAnnot] = attachmentAnnotation // Set the network route to the API, so we can reach it return c.setNatGwAPIRoute(annotations, namespace, name) @@ -752,10 +753,10 @@ func (c *Controller) genNatGwStatefulSet(gw *kubeovnv1.VpcNatGateway, oldSts *v1 externalNetworkNad := util.GetNatGwExternalNetwork(gw.Spec.ExternalSubnets) podAnnotations := map[string]string{ - util.VpcNatGatewayAnnotation: gw.Name, - util.AttachmentNetworkAnnotation: fmt.Sprintf("%s/%s", c.config.PodNamespace, externalNetworkNad), - util.LogicalSwitchAnnotation: gw.Spec.Subnet, - util.IPAddressAnnotation: gw.Spec.LanIP, + util.VpcNatGatewayAnnotation: gw.Name, + nadv1.NetworkAttachmentAnnot: fmt.Sprintf("%s/%s", c.config.PodNamespace, externalNetworkNad), + util.LogicalSwitchAnnotation: gw.Spec.Subnet, + util.IPAddressAnnotation: gw.Spec.LanIP, } // Add an interface that can reach the API server, we need access to it to probe Kube-OVN resources diff --git a/pkg/daemon/controller.go b/pkg/daemon/controller.go index eb9bd7dca4a..aade017e0da 100644 --- a/pkg/daemon/controller.go +++ b/pkg/daemon/controller.go @@ -8,6 +8,7 @@ import ( "strconv" "time" + nadutils "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/utils" "github.com/scylladb/go-set/strset" v1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" @@ -497,7 +498,7 @@ func (c *Controller) enqueuePod(oldObj, newObj interface{}) { c.podQueue.Add(key) } - attachNets, err := util.ParsePodNetworkAnnotation(newPod.Annotations[util.AttachmentNetworkAnnotation], newPod.Namespace) + attachNets, err := nadutils.ParsePodNetworkAnnotation(newPod) if err != nil { return } diff --git a/pkg/daemon/controller_linux.go b/pkg/daemon/controller_linux.go index 4b836a66662..37086f59e0a 100644 --- a/pkg/daemon/controller_linux.go +++ b/pkg/daemon/controller_linux.go @@ -12,6 +12,7 @@ import ( "strings" "syscall" + nadutils "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/utils" "github.com/kubeovn/felix/ipsets" "github.com/kubeovn/go-iptables/iptables" "github.com/vishvananda/netlink" @@ -574,7 +575,7 @@ func (c *Controller) handlePod(key string) error { } // set multus-nic bandwidth - attachNets, err := util.ParsePodNetworkAnnotation(pod.Annotations[util.AttachmentNetworkAnnotation], pod.Namespace) + attachNets, err := nadutils.ParsePodNetworkAnnotation(pod) if err != nil { klog.Error(err) return err diff --git a/pkg/daemon/controller_windows.go b/pkg/daemon/controller_windows.go index 0cb61704b52..4aaebbb7f9d 100644 --- a/pkg/daemon/controller_windows.go +++ b/pkg/daemon/controller_windows.go @@ -5,6 +5,7 @@ import ( "net" "strings" + nadutils "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/utils" "github.com/scylladb/go-set/strset" v1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" @@ -178,7 +179,7 @@ func (c *Controller) handlePod(key string) error { } // set multus-nic bandwidth - attachNets, err := util.ParsePodNetworkAnnotation(pod.Annotations[util.AttachmentNetworkAnnotation], pod.Namespace) + attachNets, err := nadutils.ParsePodNetworkAnnotation(pod) if err != nil { klog.Error(err) return err diff --git a/pkg/util/const.go b/pkg/util/const.go index a54e73260e9..d9aa017fd82 100644 --- a/pkg/util/const.go +++ b/pkg/util/const.go @@ -171,7 +171,6 @@ const ( TCPIPHeaderLength = 40 OvnProvider = "ovn" - AttachmentNetworkAnnotation = "k8s.v1.cni.cncf.io/networks" DefaultNetworkAnnotation = "v1.multus-cni.io/default-network" AttachNetworkResourceNameAnnotation = "k8s.v1.cni.cncf.io/resourceName" diff --git a/pkg/util/k8s.go b/pkg/util/k8s.go index c82d8c77d63..f54aac89a50 100644 --- a/pkg/util/k8s.go +++ b/pkg/util/k8s.go @@ -11,7 +11,7 @@ import ( "strings" "time" - nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + nadutils "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/utils" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -98,16 +98,15 @@ func PodAttachmentIPs(pod *v1.Pod, networkName string) ([]string, error) { return nil, errors.New("programmatic error: pod is nil") } - if pod.Annotations[nadv1.NetworkStatusAnnot] == "" { - return nil, fmt.Errorf("pod %s/%s has no network status annotation", pod.Namespace, pod.Name) - } - var status []nadv1.NetworkStatus - if err := json.Unmarshal([]byte(pod.Annotations[nadv1.NetworkStatusAnnot]), &status); err != nil { - return nil, fmt.Errorf("failed to unmarshal network status annotation of pod %s/%s: %w", pod.Namespace, pod.Name, err) + statuses, err := nadutils.GetNetworkStatus(pod) + if err != nil { + klog.Error(err) + return nil, fmt.Errorf("failed to get network status for pod %s/%s: %w", pod.Namespace, pod.Name, err) } - for _, s := range status { - if s.Name == networkName { - return s.IPs, nil + + for _, status := range statuses { + if status.Name == networkName { + return status.IPs, nil } } diff --git a/pkg/util/network_attachment.go b/pkg/util/network_attachment.go index 2f123a8faac..9431b223ef8 100644 --- a/pkg/util/network_attachment.go +++ b/pkg/util/network_attachment.go @@ -1,135 +1,12 @@ package util import ( - "encoding/json" - "errors" "fmt" - "net" - "regexp" - "strings" + nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" "gopkg.in/k8snetworkplumbingwg/multus-cni.v4/pkg/types" - "k8s.io/klog/v2" ) -var attachmentRegexp = regexp.MustCompile("^[a-z0-9]([-a-z0-9]*[a-z0-9])?$") - -func parsePodNetworkObjectName(podNetwork string) (string, string, string, error) { - var netNsName string - var netIfName string - var networkName string - - klog.V(3).Infof("parsePodNetworkObjectName: %s", podNetwork) - slashItems := strings.Split(podNetwork, "/") - switch len(slashItems) { - case 2: - netNsName = strings.TrimSpace(slashItems[0]) - networkName = slashItems[1] - case 1: - networkName = slashItems[0] - default: - klog.Error("parsePodNetworkObjectName: Invalid network object (failed at '/')") - return "", "", "", errors.New("parsePodNetworkObjectName: Invalid network object (failed at '/')") - } - - atItems := strings.Split(networkName, "@") - networkName = strings.TrimSpace(atItems[0]) - if len(atItems) == 2 { - netIfName = strings.TrimSpace(atItems[1]) - } else if len(atItems) != 1 { - klog.Errorf("parsePodNetworkObjectName: Invalid network object (failed at '@')") - return "", "", "", errors.New("parsePodNetworkObjectName: Invalid network object (failed at '@')") - } - - // Check and see if each item matches the specification for valid attachment name. - // "Valid attachment names must be comprised of units of the InternalDNS-1123 label format" - // [a-z0-9]([-a-z0-9]*[a-z0-9])? - // And we allow at (@), and forward slash (/) (units separated by commas) - // It must start and end alphanumerically. - allItems := []string{netNsName, networkName, netIfName} - for i := range allItems { - if !attachmentRegexp.MatchString(allItems[i]) && len([]rune(allItems[i])) > 0 { - klog.Error(fmt.Sprintf("parsePodNetworkObjectName: Failed to parse: "+ - "one or more items did not match comma-delimited format (must consist of lower case alphanumeric characters). "+ - "Must start and end with an alphanumeric character), mismatch @ '%v'", allItems[i])) - return "", "", "", fmt.Errorf("parsePodNetworkObjectName: Failed to parse: "+ - "one or more items did not match comma-delimited format (must consist of lower case alphanumeric characters). "+ - "Must start and end with an alphanumeric character), mismatch @ '%v'", allItems[i]) - } - } - - klog.V(5).Infof("parsePodNetworkObjectName: parsed: %s, %s, %s", netNsName, networkName, netIfName) - return netNsName, networkName, netIfName, nil -} - -func ParsePodNetworkAnnotation(podNetworks, defaultNamespace string) ([]*types.NetworkSelectionElement, error) { - var networks []*types.NetworkSelectionElement - - klog.V(3).Infof("parsePodNetworkAnnotation: %s, %s", podNetworks, defaultNamespace) - if podNetworks == "" { - return nil, nil - } - - if strings.ContainsAny(podNetworks, "[{\"") { - if err := json.Unmarshal([]byte(podNetworks), &networks); err != nil { - klog.Errorf("parsePodNetworkAnnotation: failed to parse pod Network Attachment Selection Annotation JSON format: %v", err) - return nil, fmt.Errorf("parsePodNetworkAnnotation: failed to parse pod Network Attachment Selection Annotation JSON format: %w", err) - } - } else { - // Comma-delimited list of network attachment object names - for _, item := range strings.Split(podNetworks, ",") { - // Remove leading and trailing whitespace. - item = strings.TrimSpace(item) - - // Parse network name (i.e. /@) - netNsName, networkName, netIfName, err := parsePodNetworkObjectName(item) - if err != nil { - klog.Errorf("parsePodNetworkAnnotation: %v", err) - return nil, fmt.Errorf("parsePodNetworkAnnotation: %w", err) - } - - networks = append(networks, &types.NetworkSelectionElement{ - Name: networkName, - Namespace: netNsName, - InterfaceRequest: netIfName, - }) - } - } - - for _, n := range networks { - if n.Namespace == "" { - n.Namespace = defaultNamespace - } - if n.MacRequest != "" { - // validate MAC address - if _, err := net.ParseMAC(n.MacRequest); err != nil { - klog.Errorf("parsePodNetworkAnnotation: failed to mac: %v", err) - return nil, fmt.Errorf("parsePodNetworkAnnotation: failed to mac: %w", err) - } - } - if n.IPRequest != nil { - for _, ip := range n.IPRequest { - // validate IP address - if strings.Contains(ip, "/") { - if _, _, err := net.ParseCIDR(ip); err != nil { - klog.Errorf("failed to parse CIDR %q: %v", ip, err) - return nil, fmt.Errorf("failed to parse CIDR %q: %w", ip, err) - } - } else if net.ParseIP(ip) == nil { - klog.Errorf("failed to parse IP address %q", ip) - return nil, fmt.Errorf("failed to parse IP address %q", ip) - } - } - } - // compatibility pre v3.2, will be removed in v4.0 - if n.DeprecatedInterfaceRequest != "" && n.InterfaceRequest == "" { - n.InterfaceRequest = n.DeprecatedInterfaceRequest - } - } - - return networks, nil -} - func IsOvnNetwork(netCfg *types.DelegateNetConf) bool { if netCfg.Conf.Type == CniTypeName { return true @@ -142,7 +19,7 @@ func IsOvnNetwork(netCfg *types.DelegateNetConf) bool { return false } -func IsDefaultNet(defaultNetAnnotation string, attach *types.NetworkSelectionElement) bool { +func IsDefaultNet(defaultNetAnnotation string, attach *nadv1.NetworkSelectionElement) bool { if defaultNetAnnotation == attach.Name || defaultNetAnnotation == fmt.Sprintf("%s/%s", attach.Namespace, attach.Name) { return true } diff --git a/pkg/util/network_attachment_test.go b/pkg/util/network_attachment_test.go index cb4b5383dc3..cd5500df534 100644 --- a/pkg/util/network_attachment_test.go +++ b/pkg/util/network_attachment_test.go @@ -1,335 +1,13 @@ package util import ( - "encoding/json" - "reflect" "testing" cnitypes "github.com/containernetworking/cni/pkg/types" + nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" "gopkg.in/k8snetworkplumbingwg/multus-cni.v4/pkg/types" ) -func TestParsePodNetworkObjectName(t *testing.T) { - tests := []struct { - name string - podNetwork string - netNsName string - networkName string - netIfName string - err string - }{ - { - name: "controversy", - podNetwork: "", - netNsName: "", - networkName: "", - netIfName: "", - err: "", - }, - { - name: "base", - podNetwork: "kube-system/lb-svc-attachment", - netNsName: "kube-system", - networkName: "lb-svc-attachment", - netIfName: "", - err: "", - }, - { - name: "baseWithoutNS", - podNetwork: "lb-svc-attachment", - netNsName: "", - networkName: "lb-svc-attachment", - netIfName: "", - err: "", - }, - { - name: "baseWithIF", - podNetwork: "kube-system/lb-svc-attachment@eth0", - netNsName: "kube-system", - networkName: "lb-svc-attachment", - netIfName: "eth0", - err: "", - }, - { - name: "errFormat", - podNetwork: "kube-system/lb-svc-attachment/1", - netNsName: "", - networkName: "lb-svc-attachment", - netIfName: "", - err: "Invalid network object", - }, - { - name: "errFormatNS", - podNetwork: "mellanox.com/cx5_sriov_switchdev", - netNsName: "", - networkName: "lb-svc-attachment", - netIfName: "", - err: "one or more items did not match comma-delimited format", - }, - { - name: "errFormatIF", - podNetwork: "kube-system/lb-svc-attachment@eth0@1", - netNsName: "kube-system", - networkName: "lb-svc-attachment", - netIfName: "eth0", - err: "Invalid network object", - }, - } - for _, c := range tests { - t.Run(c.name, func(t *testing.T) { - netNsName, networkName, netIfName, err := parsePodNetworkObjectName(c.podNetwork) - if !ErrorContains(err, c.err) && (netNsName != c.netNsName || networkName != c.networkName || netIfName != c.netIfName) { - t.Errorf("%v expected %v %v %v and err %v, but %v %v %v and err %v got", - c.podNetwork, c.netNsName, c.networkName, c.netIfName, c.err, netNsName, networkName, netIfName, err) - } - }) - } -} - -func TestParsePodNetworkAnnotation(t *testing.T) { - correctJSON0, _ := json.Marshal([]types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "eth0", - MacRequest: "00:0c:29:9a:96:74", - DeprecatedInterfaceRequest: "eth0", - IPRequest: []string{"192.168.50.6"}, - }, - }) - correctJSON0IP, _ := json.Marshal([]types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "eth0", - MacRequest: "00:0c:29:9a:96:74", - DeprecatedInterfaceRequest: "eth0", - IPRequest: []string{"192.168.50.6/20"}, - }, - }) - errJSON0, _ := json.Marshal(types.NetworkSelectionElement{ - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "eth0", - MacRequest: "00:0c:29:9a:96:74", - DeprecatedInterfaceRequest: "eth0", - IPRequest: []string{"192.168.50.6"}, - }) - errJSONMac, _ := json.Marshal([]types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "eth0", - MacRequest: "123", - DeprecatedInterfaceRequest: "eth0", - IPRequest: []string{"192.168.50.6"}, - }, - }) - errJSON0IP1, _ := json.Marshal([]types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "eth0", - MacRequest: "00:0c:29:9a:96:74", - DeprecatedInterfaceRequest: "eth0", - IPRequest: []string{"192.168.6"}, - }, - }) - errJSON0IP2, _ := json.Marshal([]types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "eth0", - MacRequest: "00:0c:29:9a:96:74", - DeprecatedInterfaceRequest: "eth0", - IPRequest: []string{"192.168.6/20"}, - }, - }) - correctJSON0IfReq, _ := json.Marshal([]types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "", - MacRequest: "00:0c:29:9a:96:74", - DeprecatedInterfaceRequest: "eth0", - IPRequest: []string{"192.168.50.6"}, - }, - }) - - tests := []struct { - name string - podNetworks string - defaultNamespace string - exp []*types.NetworkSelectionElement - err string - }{ - { - name: "base", - podNetworks: "kube-system/lb-svc-attachment@eth0", - defaultNamespace: "kube-system", - exp: []*types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "eth0", - }, - }, - err: "", - }, - { - name: "baseWithIF", - podNetworks: "kube-system/lb-svc-attachment", - defaultNamespace: "kube-system", - exp: []*types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "", - }, - }, - err: "", - }, - { - name: "baseWithoutNS", - podNetworks: "lb-svc-attachment", - defaultNamespace: "kube-system", - exp: []*types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "", - }, - }, - err: "", - }, - { - name: "baseWithoutNS", - podNetworks: "lb-svc-attachment", - defaultNamespace: "kube-system", - exp: []*types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "", - }, - }, - err: "", - }, - { - name: "baseWithIFandNS", - podNetworks: "kube-system/lb-svc-attachment@eth0", - defaultNamespace: "kube-system", - exp: []*types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "eth0", - }, - }, - err: "", - }, - { - name: "correctJson", - podNetworks: string(correctJSON0), - defaultNamespace: "kube-system", - exp: []*types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "eth0", - MacRequest: "00:0c:29:9a:96:74", - DeprecatedInterfaceRequest: "eth0", - IPRequest: []string{"192.168.50.6"}, - }, - }, - err: "", - }, - { - name: "correctJsonIP", - podNetworks: string(correctJSON0IP), - defaultNamespace: "kube-system", - exp: []*types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "eth0", - MacRequest: "00:0c:29:9a:96:74", - DeprecatedInterfaceRequest: "eth0", - IPRequest: []string{"192.168.50.6/20"}, - }, - }, - err: "", - }, - { - name: "correctJsonIfReq", - podNetworks: string(correctJSON0IfReq), - defaultNamespace: "kube-system", - exp: []*types.NetworkSelectionElement{ - { - Name: "lb-svc-attachment", - Namespace: "kube-system", - InterfaceRequest: "eth0", - MacRequest: "00:0c:29:9a:96:74", - DeprecatedInterfaceRequest: "eth0", - IPRequest: []string{"192.168.50.6"}, - }, - }, - err: "", - }, - { - name: "errJson", - podNetworks: string(errJSON0), - defaultNamespace: "kube-system", - exp: nil, - err: "json: cannot unmarshal object into Go value", - }, - { - name: "errJSONMac", - podNetworks: string(errJSONMac), - defaultNamespace: "kube-system", - exp: nil, - err: "invalid MAC address", - }, - { - name: "errJsonIP1", - podNetworks: string(errJSON0IP1), - defaultNamespace: "kube-system", - exp: nil, - err: "failed to parse IP address", - }, - { - name: "errJsonIP2", - podNetworks: string(errJSON0IP2), - defaultNamespace: "kube-system", - exp: nil, - err: "invalid CIDR address", - }, - { - name: "errFormat", - podNetworks: "kube-system/lb-svc-attachment@eth0@1", - defaultNamespace: "kube-system", - exp: nil, - err: "Invalid network object", - }, - { - name: "errNull", - podNetworks: "", - defaultNamespace: "kube-system", - exp: nil, - err: "", - }, - } - for _, c := range tests { - t.Run(c.name, func(t *testing.T) { - ele, err := ParsePodNetworkAnnotation(c.podNetworks, c.defaultNamespace) - if !ErrorContains(err, c.err) || !reflect.DeepEqual(ele, c.exp) { - t.Errorf("%v, %v expected %v and err %v, but %v and err %v got", - c.podNetworks, c.defaultNamespace, c.exp[0], c.err, ele[0], err) - } - }) - } -} - func TestIsOvnNetwork(t *testing.T) { tests := []struct { name string @@ -381,13 +59,13 @@ func TestIsDefaultNet(t *testing.T) { tests := []struct { name string defaultNetAnnotation string - attach *types.NetworkSelectionElement + attach *nadv1.NetworkSelectionElement expt bool }{ { name: "base", defaultNetAnnotation: "nm", - attach: &types.NetworkSelectionElement{ + attach: &nadv1.NetworkSelectionElement{ Name: "nm", Namespace: "ns", }, @@ -396,7 +74,7 @@ func TestIsDefaultNet(t *testing.T) { { name: "baseWithNS", defaultNetAnnotation: "ns/nm", - attach: &types.NetworkSelectionElement{ + attach: &nadv1.NetworkSelectionElement{ Name: "nm", Namespace: "ns", }, @@ -405,7 +83,7 @@ func TestIsDefaultNet(t *testing.T) { { name: "errFormat", defaultNetAnnotation: "err", - attach: &types.NetworkSelectionElement{ + attach: &nadv1.NetworkSelectionElement{ Name: "nm", Namespace: "ns", }, diff --git a/test/e2e/framework/cni.go b/test/e2e/framework/cni.go index 4e62b1c6535..df0ce43dca2 100644 --- a/test/e2e/framework/cni.go +++ b/test/e2e/framework/cni.go @@ -36,8 +36,9 @@ func MakeMacvlanNetworkAttachmentDefinition(name, namespace, master, mode, provi config := &MacvlanNetConf{ NetConf: netconf.NetConf{ NetConf: types.NetConf{ - CNIVersion: CNIVersion, - Type: "macvlan", + CNIVersion: CNIVersion, + Type: "macvlan", + Capabilities: map[string]bool{"mac": true}, }, IPAM: &netconf.IPAMConf{ Type: util.CniTypeName, diff --git a/test/e2e/kube-ovn/node/node.go b/test/e2e/kube-ovn/node/node.go index d88bee9da15..24500323285 100644 --- a/test/e2e/kube-ovn/node/node.go +++ b/test/e2e/kube-ovn/node/node.go @@ -80,7 +80,7 @@ var _ = framework.OrderedDescribe("[group:node]", func() { podName = "pod-" + framework.RandomSuffix() ginkgo.By("Creating pod " + podName + " with host network on node " + node.Name) - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePrivilegedPod(namespaceName, podName, nil, nil, f.KubeOVNImage, cmd, nil) pod.Spec.NodeName = node.Name pod.Spec.HostNetwork = true @@ -120,7 +120,7 @@ var _ = framework.OrderedDescribe("[group:node]", func() { pod = podClient.CreateSync(pod) ginkgo.By("Creating pod " + hostPodName + " with host network") - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} hostPod := framework.MakePod(namespaceName, hostPodName, nil, nil, f.KubeOVNImage, cmd, nil) hostPod.Spec.HostNetwork = true hostPod = podClient.CreateSync(hostPod) @@ -171,7 +171,7 @@ var _ = framework.OrderedDescribe("[group:node]", func() { }, "cluster ips are not empty") ginkgo.By("Creating pod " + hostPodName + " with host network") - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} hostPod := framework.MakePod(namespaceName, hostPodName, nil, nil, f.KubeOVNImage, cmd, nil) hostPod.Spec.HostNetwork = true hostPod = podClient.CreateSync(hostPod) @@ -230,7 +230,7 @@ var _ = framework.SerialDescribe("[group:node]", func() { podName = "pod-" + framework.RandomSuffix() ginkgo.By("Creating pod " + podName + " with host network") - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePrivilegedPod(namespaceName, podName, nil, nil, f.KubeOVNImage, cmd, nil) pod.Spec.NodeName = node.Name pod.Spec.HostNetwork = true diff --git a/test/e2e/kube-ovn/pod/pod_routes.go b/test/e2e/kube-ovn/pod/pod_routes.go index f5daeeb6835..bd32cd6f26b 100644 --- a/test/e2e/kube-ovn/pod/pod_routes.go +++ b/test/e2e/kube-ovn/pod/pod_routes.go @@ -58,7 +58,7 @@ var _ = framework.SerialDescribe("[group:pod]", func() { annotations := map[string]string{ util.NorthGatewayAnnotation: northGateway, } - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePod(namespaceName, podName, nil, annotations, f.KubeOVNImage, cmd, nil) pod = podClient.CreateSync(pod) @@ -137,7 +137,7 @@ var _ = framework.SerialDescribe("[group:pod]", func() { annotations := map[string]string{ util.RoutesAnnotation: string(buff), } - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePrivilegedPod(namespaceName, podName, nil, annotations, f.KubeOVNImage, cmd, nil) pod = podClient.CreateSync(pod) diff --git a/test/e2e/kube-ovn/service/service.go b/test/e2e/kube-ovn/service/service.go index ae4cf47a506..b4e28a48d5e 100644 --- a/test/e2e/kube-ovn/service/service.go +++ b/test/e2e/kube-ovn/service/service.go @@ -88,7 +88,7 @@ var _ = framework.Describe("[group:service]", func() { }, "node port is allocated") ginkgo.By("Creating pod " + hostPodName + " with host network") - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} hostPod := framework.MakePod(namespaceName, hostPodName, nil, nil, f.KubeOVNImage, cmd, nil) hostPod.Spec.HostNetwork = true _ = podClient.CreateSync(hostPod) diff --git a/test/e2e/kube-ovn/subnet/subnet.go b/test/e2e/kube-ovn/subnet/subnet.go index d9932dd350b..991f41bb509 100644 --- a/test/e2e/kube-ovn/subnet/subnet.go +++ b/test/e2e/kube-ovn/subnet/subnet.go @@ -346,7 +346,7 @@ var _ = framework.Describe("[group:subnet]", func() { } ginkgo.By("Creating pod " + podName) - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePod(namespaceName, podName, nil, nil, f.KubeOVNImage, cmd, nil) _ = podClient.CreateSync(pod) @@ -453,7 +453,7 @@ var _ = framework.Describe("[group:subnet]", func() { } ginkgo.By("Creating pod " + podName) - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePod(namespaceName, podName, nil, nil, f.KubeOVNImage, cmd, nil) _ = podClient.CreateSync(pod) @@ -491,7 +491,7 @@ var _ = framework.Describe("[group:subnet]", func() { framework.ExpectConsistOf(strings.Split(subnet.Spec.GatewayNode, ","), gatewayNodes) ginkgo.By("Creating pod " + podName) - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePod(namespaceName, podName, nil, nil, f.KubeOVNImage, cmd, nil) _ = podClient.CreateSync(pod) @@ -593,7 +593,7 @@ var _ = framework.Describe("[group:subnet]", func() { subnet = subnetClient.CreateSync(subnet) ginkgo.By("Creating pod " + podName) - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePod(namespaceName, podName, nil, nil, f.KubeOVNImage, cmd, nil) pod = podClient.CreateSync(pod) diff --git a/test/e2e/lb-svc/e2e_test.go b/test/e2e/lb-svc/e2e_test.go index d62fe90ae0a..aae98882b3e 100644 --- a/test/e2e/lb-svc/e2e_test.go +++ b/test/e2e/lb-svc/e2e_test.go @@ -217,7 +217,7 @@ var _ = framework.SerialDescribe("[group:lb-svc]", func() { ginkgo.By("Creating client pod " + clientPodName) annotations = map[string]string{nadv1.NetworkAttachmentAnnot: fmt.Sprintf("%s/%s", namespaceName, nadName)} - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} clientPod := framework.MakePod(namespaceName, clientPodName, nil, annotations, f.KubeOVNImage, cmd, nil) clientPod = podClient.CreateSync(clientPod) @@ -324,7 +324,7 @@ var _ = framework.SerialDescribe("[group:lb-svc]", func() { ginkgo.By("Creating client pod " + clientPodName) annotations = map[string]string{nadv1.NetworkAttachmentAnnot: fmt.Sprintf("%s/%s", namespaceName, nadName)} - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} clientPod := framework.MakePod(namespaceName, clientPodName, nil, annotations, f.KubeOVNImage, cmd, nil) clientPod = podClient.CreateSync(clientPod) diff --git a/test/e2e/multus/e2e_test.go b/test/e2e/multus/e2e_test.go index 4f0e791a24a..8c7b19af3d6 100644 --- a/test/e2e/multus/e2e_test.go +++ b/test/e2e/multus/e2e_test.go @@ -1,11 +1,14 @@ package multus import ( + "encoding/json" "flag" "fmt" "testing" nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + nadutils "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/utils" + "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" "k8s.io/kubernetes/test/e2e" k8sframework "k8s.io/kubernetes/test/e2e/framework" @@ -81,7 +84,7 @@ var _ = framework.SerialDescribe("[group:multus]", func() { ginkgo.By("Creating pod " + podName) annotations := map[string]string{nadv1.NetworkAttachmentAnnot: fmt.Sprintf("%s/%s", nad.Namespace, nad.Name)} - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePrivilegedPod(namespaceName, podName, nil, annotations, f.KubeOVNImage, cmd, nil) pod = podClient.CreateSync(pod) @@ -184,7 +187,7 @@ var _ = framework.SerialDescribe("[group:multus]", func() { ginkgo.By("Creating pod " + podName) annotations := map[string]string{nadv1.NetworkAttachmentAnnot: fmt.Sprintf("%s/%s", nad.Namespace, nad.Name)} - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePrivilegedPod(namespaceName, podName, nil, annotations, f.KubeOVNImage, cmd, nil) pod = podClient.CreateSync(pod) @@ -263,21 +266,45 @@ var _ = framework.SerialDescribe("[group:multus]", func() { subnet.Spec.Provider = provider subnet = subnetClient.CreateSync(subnet) - ginkgo.By("Creating pod " + podName) - annotations := map[string]string{nadv1.NetworkAttachmentAnnot: fmt.Sprintf("%s/%s", nad.Namespace, nad.Name)} - cmd := []string{"sh", "-c", "sleep infinity"} + mac := util.GenerateMac() + ginkgo.By("Generating networks annotation with MAC " + mac) + networks := []*nadv1.NetworkSelectionElement{{ + Name: nad.Name, + Namespace: nad.Namespace, + MacRequest: mac, + }} + networksAnnotation, err := json.Marshal(networks) + framework.ExpectNoError(err) + framework.Logf("networks annotation: %s", string(networksAnnotation)) + + ginkgo.By("Creating pod " + podName + " with MAC address " + mac) + annotations := map[string]string{nadv1.NetworkAttachmentAnnot: string(networksAnnotation)} + cmd := []string{"sleep", "infinity"} pod := framework.MakePrivilegedPod(namespaceName, podName, nil, annotations, f.KubeOVNImage, cmd, nil) pod = podClient.CreateSync(pod) ginkgo.By("Validating pod annotations") framework.ExpectHaveKey(pod.Annotations, nadv1.NetworkStatusAnnot) framework.Logf("pod network status:\n%s", pod.Annotations[nadv1.NetworkStatusAnnot]) + statuses, err := nadutils.GetNetworkStatus(pod) + framework.ExpectNoError(err) + var ifaceName string + nadKey := cache.MetaObjectToName(nad).String() + for _, status := range statuses { + if status.Name == nadKey { + framework.ExpectEqual(status.Mac, mac) + ifaceName = status.Interface + break + } + } + framework.ExpectNotEmpty(ifaceName) cidr := pod.Annotations[fmt.Sprintf(util.CidrAnnotationTemplate, provider)] ip := pod.Annotations[fmt.Sprintf(util.IPAddressAnnotationTemplate, provider)] gateway := pod.Annotations[fmt.Sprintf(util.GatewayAnnotationTemplate, provider)] framework.ExpectIPInCIDR(ip, cidr) framework.ExpectIPInCIDR(gateway, cidr) framework.ExpectNotHaveKey(pod.Annotations, fmt.Sprintf(util.MacAddressAnnotationTemplate, provider)) + // framework.ExpectHaveKeyWithValue(pod.Annotations, fmt.Sprintf(util.MacAddressAnnotationTemplate, provider), mac) ipName := ovs.PodNameToPortName(podName, namespaceName, provider) ginkgo.By("Validating IP resource " + ipName) @@ -298,6 +325,14 @@ var _ = framework.SerialDescribe("[group:multus]", func() { framework.ExpectHaveKeyWithValue(ipCR.Labels, util.IPReservedLabel, "false") } + ginkgo.By("Retrieving MAC address of interface " + ifaceName) + links, err := iproute.AddressShow(ifaceName, func(cmd ...string) ([]byte, []byte, error) { + return framework.KubectlExec(namespaceName, podName, cmd...) + }) + framework.ExpectNoError(err) + framework.ExpectHaveLen(links, 1) + framework.ExpectEqual(links[0].Address, mac) + ginkgo.By("Retrieving pod routes") podRoutes, err := iproute.RouteShow("", "", func(cmd ...string) ([]byte, []byte, error) { return framework.KubectlExec(namespaceName, podName, cmd...) @@ -365,21 +400,45 @@ var _ = framework.SerialDescribe("[group:multus]", func() { nad = nadClient.Create(nad) framework.Logf("created network attachment definition config:\n%s", nad.Spec.Config) - ginkgo.By("Creating pod " + podName) - annotations := map[string]string{nadv1.NetworkAttachmentAnnot: fmt.Sprintf("%s/%s", nad.Namespace, nad.Name)} - cmd := []string{"sh", "-c", "sleep infinity"} + mac := util.GenerateMac() + ginkgo.By("Generating networks annotation with MAC " + mac) + networks := []*nadv1.NetworkSelectionElement{{ + Name: nad.Name, + Namespace: nad.Namespace, + MacRequest: mac, + }} + networksAnnotation, err := json.Marshal(networks) + framework.ExpectNoError(err) + framework.Logf("networks annotation: %s", string(networksAnnotation)) + + ginkgo.By("Creating pod " + podName + " with MAC address " + mac) + annotations := map[string]string{nadv1.NetworkAttachmentAnnot: string(networksAnnotation)} + cmd := []string{"sleep", "infinity"} pod := framework.MakePrivilegedPod(namespaceName, podName, nil, annotations, f.KubeOVNImage, cmd, nil) pod = podClient.CreateSync(pod) ginkgo.By("Validating pod annotations") framework.ExpectHaveKey(pod.Annotations, nadv1.NetworkStatusAnnot) framework.Logf("pod network status:\n%s", pod.Annotations[nadv1.NetworkStatusAnnot]) + statuses, err := nadutils.GetNetworkStatus(pod) + framework.ExpectNoError(err) + var ifaceName string + nadKey := cache.MetaObjectToName(nad).String() + for _, status := range statuses { + if status.Name == nadKey { + framework.ExpectEqual(status.Mac, mac) + ifaceName = status.Interface + break + } + } + framework.ExpectNotEmpty(ifaceName) cidr := pod.Annotations[fmt.Sprintf(util.CidrAnnotationTemplate, provider)] ip := pod.Annotations[fmt.Sprintf(util.IPAddressAnnotationTemplate, provider)] gateway := pod.Annotations[fmt.Sprintf(util.GatewayAnnotationTemplate, provider)] framework.ExpectIPInCIDR(ip, cidr) framework.ExpectIPInCIDR(gateway, cidr) framework.ExpectNotHaveKey(pod.Annotations, fmt.Sprintf(util.MacAddressAnnotationTemplate, provider)) + // framework.ExpectHaveKeyWithValue(pod.Annotations, fmt.Sprintf(util.MacAddressAnnotationTemplate, provider), mac) ipName := ovs.PodNameToPortName(podName, namespaceName, provider) ginkgo.By("Validating IP resource " + ipName) @@ -400,6 +459,14 @@ var _ = framework.SerialDescribe("[group:multus]", func() { framework.ExpectHaveKeyWithValue(ipCR.Labels, util.IPReservedLabel, "false") } + ginkgo.By("Retrieving MAC address of interface " + ifaceName) + links, err := iproute.AddressShow(ifaceName, func(cmd ...string) ([]byte, []byte, error) { + return framework.KubectlExec(namespaceName, podName, cmd...) + }) + framework.ExpectNoError(err) + framework.ExpectHaveLen(links, 1) + framework.ExpectEqual(links[0].Address, mac) + ginkgo.By("Retrieving pod routes") podRoutes, err := iproute.RouteShow("", "", func(cmd ...string) ([]byte, []byte, error) { return framework.KubectlExec(namespaceName, podName, cmd...) diff --git a/test/e2e/ovn-vpc-nat-gw/e2e_test.go b/test/e2e/ovn-vpc-nat-gw/e2e_test.go index bd7c22b095a..264c637a2e1 100644 --- a/test/e2e/ovn-vpc-nat-gw/e2e_test.go +++ b/test/e2e/ovn-vpc-nat-gw/e2e_test.go @@ -584,7 +584,7 @@ var _ = framework.Describe("[group:ovn-vpc-nat-gw]", func() { podOnNodeName := fmt.Sprintf("no-bfd-%s", node) ginkgo.By("Creating no bfd pod " + podOnNodeName + " with subnet " + noBfdSubnetName) annotations := map[string]string{util.LogicalSwitchAnnotation: noBfdSubnetName} - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePod(namespaceName, podOnNodeName, nil, annotations, f.KubeOVNImage, cmd, nil) pod.Spec.NodeName = node _ = podClient.CreateSync(pod) @@ -592,7 +592,7 @@ var _ = framework.Describe("[group:ovn-vpc-nat-gw]", func() { ginkgo.By("Creating pod with fip") annotations := map[string]string{util.LogicalSwitchAnnotation: noBfdSubnetName} - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} fipPod := framework.MakePod(namespaceName, fipPodName, nil, annotations, f.KubeOVNImage, cmd, nil) fipPod = podClient.CreateSync(fipPod) podEip := framework.MakeOvnEip(podEipName, underlaySubnetName, "", "", "", "") @@ -768,7 +768,7 @@ var _ = framework.Describe("[group:ovn-vpc-nat-gw]", func() { podOnNodeName := fmt.Sprintf("no-bfd-extra-%s", node) ginkgo.By("Creating no bfd extra pod " + podOnNodeName + " with subnet " + noBfdExtraSubnetName) annotations := map[string]string{util.LogicalSwitchAnnotation: noBfdExtraSubnetName} - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePod(namespaceName, podOnNodeName, nil, annotations, f.KubeOVNImage, cmd, nil) pod.Spec.NodeName = node _ = podClient.CreateSync(pod) @@ -933,7 +933,7 @@ var _ = framework.Describe("[group:ovn-vpc-nat-gw]", func() { podOnNodeName := fmt.Sprintf("bfd-%s", node) ginkgo.By("Creating bfd pod " + podOnNodeName + " with subnet " + bfdSubnetName) annotations := map[string]string{util.LogicalSwitchAnnotation: bfdSubnetName} - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} pod := framework.MakePod(namespaceName, podOnNodeName, nil, annotations, f.KubeOVNImage, cmd, nil) pod.Spec.NodeName = node _ = podClient.CreateSync(pod) diff --git a/test/e2e/vip/e2e_test.go b/test/e2e/vip/e2e_test.go index dfcb233bc3a..dfc9d42c985 100644 --- a/test/e2e/vip/e2e_test.go +++ b/test/e2e/vip/e2e_test.go @@ -264,7 +264,7 @@ var _ = framework.Describe("[group:vip]", func() { framework.ExpectNotEqual(vip1.Status.Mac, vip2.Status.Mac) annotations := map[string]string{util.AAPsAnnotation: vip1Name} - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} ginkgo.By("Creating pod1 support allowed address pair using " + vip1Name) aapPod1 := framework.MakePrivilegedPod(namespaceName, aapPodName1, nil, annotations, f.KubeOVNImage, cmd, nil) aapPod1 = podClient.CreateSync(aapPod1) diff --git a/test/e2e/vpc-egress-gateway/e2e_test.go b/test/e2e/vpc-egress-gateway/e2e_test.go index 0c1e7cd0024..e737410914c 100644 --- a/test/e2e/vpc-egress-gateway/e2e_test.go +++ b/test/e2e/vpc-egress-gateway/e2e_test.go @@ -14,6 +14,7 @@ import ( "time" dockernetwork "github.com/docker/docker/api/types/network" + nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -494,7 +495,7 @@ func vegTest(f *framework.Framework, bfd bool, provider, nadName, vpcName, inter annotations, err := routes.ToAnnotations() framework.ExpectNoError(err) attachmentNetworkName := fmt.Sprintf("%s/%s", namespaceName, nadName) - annotations[util.AttachmentNetworkAnnotation] = attachmentNetworkName + annotations[nadv1.NetworkAttachmentAnnot] = attachmentNetworkName port := strconv.Itoa(8000 + rand.IntN(1000)) args := []string{"netexec", "--http-port", port} svrPod := framework.MakePrivilegedPod(namespaceName, svrPodName, nil, annotations, framework.AgnhostImage, nil, args) diff --git a/test/e2e/webhook/pod/pod.go b/test/e2e/webhook/pod/pod.go index 5791f9461e2..b949b97ca0d 100644 --- a/test/e2e/webhook/pod/pod.go +++ b/test/e2e/webhook/pod/pod.go @@ -56,7 +56,7 @@ var _ = framework.Describe("[group:webhook-pod]", func() { framework.ConformanceIt("validate static ip by pod annotation", func() { ginkgo.By("Creating pod " + podName) - cmd := []string{"sh", "-c", "sleep infinity"} + cmd := []string{"sleep", "infinity"} ginkgo.By("validate ip validation") annotations := map[string]string{