Skip to content

Commit

Permalink
Antrea's native secondary network configuration e2e framework.
Browse files Browse the repository at this point in the history
Signed-off-by: Arunkumar Velayutham <arunkumar.velayutham@intel.com>
  • Loading branch information
arunvelayutham committed Nov 29, 2022
1 parent e7486d5 commit 7746f3a
Show file tree
Hide file tree
Showing 3 changed files with 471 additions and 0 deletions.
134 changes: 134 additions & 0 deletions test/e2e-secondary-network/framework.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright 2022 Antrea Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package e2e

import (
"fmt"
"log"
"net"
"os"
"path/filepath"
"strconv"
"strings"
"time"

corev1 "k8s.io/api/core/v1"
//restclient "k8s.io/client-go/rest"

antreae2e "antrea.io/antrea/test/e2e"
)

type SNTestData struct {
e2eTestData *antreae2e.TestData
logsDirForTestCase string
}

func createDirectory(path string) error {
return os.Mkdir(path, 0700)
}

const (
busyboxImage = "projects.registry.vmware.com/antrea/busybox"
defaultInterval = 1 * time.Second
)

var SNtestData *SNTestData

type PodIPs struct {
ipv4 *net.IP
ipv6 *net.IP
ipStrings []string
}

type podInfo struct {
name string
os string
nodeName string
namespace string
}

type ClusterInfo struct {
controlPlaneNodeName string
}

var clusterInfo ClusterInfo

// podWaitForRunning polls the k8s apiserver until the specified Pod is in the "running" state (or
// until the provided timeout expires).
func (data *SNTestData) podWaitForRunning(timeout time.Duration, name, namespace string) error {
_, err := data.e2eTestData.PodWaitFor(timeout, name, namespace, func(pod *corev1.Pod) (bool, error) {
return pod.Status.Phase == corev1.PodRunning, nil
})
return err
}

func (data *SNTestData) setupLogDirectoryForTest(testName string) error {
path := filepath.Join(testOptions.logsExportDir, testName)
// remove directory if it already exists. This ensures that we start with an empty directory
_ = os.RemoveAll(path)
err := createDirectory(path)
if err != nil {
return err
}
data.logsDirForTestCase = path
return nil
}

func (data *SNTestData) createClient(kubeconfigPath string) error {
e2edata = &antreae2e.TestData{}
if err := e2edata.CreateClient(kubeconfigPath); err != nil {
log.Fatalf("Error when creating K8s ClientSet: %v", err)
return err
}
data.e2eTestData = e2edata
return nil
}

func (data *SNTestData) RunPingCommandFromTestPod(podInfo podInfo, ns string, targetPodIPs *PodIPs, ctrName string, count int, size int) error {
if podInfo.os != "linux" {
return fmt.Errorf("OS of Pod '%s' is supported", podInfo.name)
}
if targetPodIPs.ipv4 != nil {
cmdV4 := getPingCommand(count, size, podInfo.os, targetPodIPs.ipv4)
if stdout, stderr, err := data.e2eTestData.RunCommandFromPod(ns, podInfo.name, ctrName, cmdV4); err != nil {
return fmt.Errorf("error when running ping command '%s': %v - stdout: %s - stderr: %s", strings.Join(cmdV4, " "), err, stdout, stderr)
}
}
if targetPodIPs.ipv6 != nil {
cmdV6 := getPingCommand(count, size, podInfo.os, targetPodIPs.ipv6)
if stdout, stderr, err := data.e2eTestData.RunCommandFromPod(ns, podInfo.name, ctrName, cmdV6); err != nil {
return fmt.Errorf("error when running ping command '%s': %v - stdout: %s - stderr: %s", strings.Join(cmdV6, " "), err, stdout, stderr)
}
}
return nil
}

func getPingCommand(count int, size int, os string, ip *net.IP) []string {
countOption, sizeOption := "-c", "-s"
if os == "windows" {
countOption = "-n"
sizeOption = "-l"
}
cmd := []string{"ping", countOption, strconv.Itoa(count)}
if size != 0 {
cmd = append(cmd, sizeOption, strconv.Itoa(size))
}
if ip.To4() != nil {
cmd = append(cmd, "-4", ip.String())
} else {
cmd = append(cmd, "-6", ip.String())
}
return cmd
}
95 changes: 95 additions & 0 deletions test/e2e-secondary-network/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright 2022 Antrea Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package main under directory cmd parses and validates user input,
// instantiates and initializes objects imported from pkg, and runs
// the process

package e2e

import (
"flag"
"log"
"os"
"path"
"testing"

antreae2e "antrea.io/antrea/test/e2e"
)

type TestOptions struct {
logsExportDir string
enableAntreaIPAM bool
skipCases string
linuxVMs string
}

var e2edata *antreae2e.TestData
var testOptions TestOptions
var homeDir, _ = os.UserHomeDir()

// setupLogging creates a temporary directory to export the test logs if necessary. If a directory
// was provided by the user, it checks that the directory exists.
func (tOptions *TestOptions) setupLogging() func() {
if tOptions.logsExportDir == "" {
name, err := os.MkdirTemp("", "antrea-e2e-secondary-test-")
if err != nil {
log.Fatalf("Error when creating temporary directory to export logs: %v", err)
}
log.Printf("Test logs (if any) will be exported under the '%s' directory", name)
tOptions.logsExportDir = name
// we will delete the temporary directory if no logs are exported
return func() {
if empty, _ := antreae2e.IsDirEmpty(name); empty {
log.Printf("Removing empty logs directory '%s'", name)
_ = os.Remove(name)
} else {
log.Printf("Logs exported under '%s', it is your responsibility to delete the directory when you no longer need it", name)
}
}
}
fInfo, err := os.Stat(tOptions.logsExportDir)
if err != nil {
log.Fatalf("Cannot stat provided directory '%s': %v", tOptions.logsExportDir, err)
}
if !fInfo.Mode().IsDir() {
log.Fatalf("'%s' is not a valid directory", tOptions.logsExportDir)
}
// no-op cleanup function
return func() {}
}

func testMain(m *testing.M) int {
flag.StringVar(&testOptions.logsExportDir, "logs-export-dir", "", "Export directory for test logs")
flag.BoolVar(&testOptions.enableAntreaIPAM, "antrea-ipam", false, "Run tests with AntreaIPAM")
flag.StringVar(&testOptions.skipCases, "skip", "", "Key words to skip cases")
flag.StringVar(&testOptions.linuxVMs, "linuxVMs", "", "hostname of Linux VMs")
flag.Parse()

cleanupLogging := testOptions.setupLogging()
defer cleanupLogging()

SNtestData = &SNTestData{}
log.Println("Creating K8s ClientSet")
kubeconfigPath := path.Join(homeDir, ".kube", "secondary_network_cluster", "config")
if err := SNtestData.createClient(kubeconfigPath); err != nil {
log.Fatalf("Error when creating K8s ClientSet: %v", err)
}
ret := m.Run()
return ret
}

func TestMain(m *testing.M) {
os.Exit(testMain(m))
}
Loading

0 comments on commit 7746f3a

Please sign in to comment.