diff options
Diffstat (limited to 'build/conformance/e2e-runner/run.go')
| -rw-r--r-- | build/conformance/e2e-runner/run.go | 291 |
1 files changed, 20 insertions, 271 deletions
diff --git a/build/conformance/e2e-runner/run.go b/build/conformance/e2e-runner/run.go index 1c18eac39..cdf742824 100644 --- a/build/conformance/e2e-runner/run.go +++ b/build/conformance/e2e-runner/run.go @@ -17,8 +17,6 @@ limitations under the License. package main import ( - "context" - "encoding/json" "fmt" "io" "log" @@ -28,19 +26,10 @@ import ( "path/filepath" "strings" "syscall" - "time" "github.com/pkg/errors" - "gopkg.in/yaml.v3" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/strategicpatch" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/clientcmd" - "k8s.io/client-go/util/retry" + + "github.com/kubeedge/kubeedge/build/conformance/util" ) const ( @@ -61,8 +50,6 @@ const ( defaultReportPrefix = "conformance" defaultGinkgoBinary = "/usr/local/bin/ginkgo" defaultTestBinary = "/usr/local/bin/e2e.test" - - edgeNodeLabelKey = "node-role.kubernetes.io/edge" ) func main() { @@ -71,7 +58,7 @@ func main() { go func() { sig := <-c log.Printf("Received signal %v, exiting", sig) - err := afterRunConformance() + err := util.AfterRunConformance() if err != nil { log.Printf("failed to cleanup after conformance, err: %v\n", err) } @@ -83,19 +70,19 @@ func main() { } func RunE2E() error { - err := beforeRunConformance() + err := util.BeforeRunConformance() if err != nil { return fmt.Errorf("failed to prepare for run conformance, err: %v", err) } defer func() { - err := afterRunConformance() + err := util.AfterRunConformance() if err != nil { log.Printf("failed to cleanup after conformance, err: %v\n", err) } }() - resultsDir := getEnvWithDefault(resultsDirEnvKey, defaultResultsDir) + resultsDir := util.GetEnvWithDefault(resultsDirEnvKey, defaultResultsDir) // Print the output to stdout and a logfile which will be returned // as part of the results' tarball. @@ -112,7 +99,7 @@ func RunE2E() error { return err } - log.Printf("Running command:\n%v\n", cmdInfo(cmd)) + log.Printf("Running command:\n%v\n", util.CmdInfo(cmd)) err = cmd.Start() if err != nil { @@ -125,7 +112,7 @@ func RunE2E() error { func makeCmd(w io.Writer) (*exec.Cmd, error) { var ginkgoArgs []string - skipCommands, err := skipCommands() + skipCommands, err := util.SkipCommands() if err != nil { return nil, err } @@ -134,277 +121,39 @@ func makeCmd(w io.Writer) (*exec.Cmd, error) { ginkgoArgs = append(ginkgoArgs, "--skip="+skipped) - skipEnvValue := getEnvWithDefault(skipEnvKey, "") + skipEnvValue := util.GetEnvWithDefault(skipEnvKey, "") if len(skipEnvValue) > 0 { ginkgoArgs = append(ginkgoArgs, "--skip="+skipEnvValue) } - focusEnvValue := getEnvWithDefault(focusEnvKey, defaultFocus) + focusEnvValue := util.GetEnvWithDefault(focusEnvKey, defaultFocus) ginkgoArgs = append(ginkgoArgs, "--focus="+focusEnvValue) ginkgoArgs = append(ginkgoArgs, "--noColor=true") - if len(getEnvWithDefault(dryRunEnvKey, "")) > 0 { + if len(util.GetEnvWithDefault(dryRunEnvKey, "")) > 0 { ginkgoArgs = append(ginkgoArgs, "--dryRun=true") } extraArgs := []string{ - "--report-dir=" + getEnvWithDefault(resultsDirEnvKey, defaultResultsDir), - "--report-prefix=" + getEnvWithDefault(reportPrefixEnvKey, defaultReportPrefix), - "--kubeconfig=" + getEnvWithDefault(kubeConfigEnvKey, ""), - "--image-url=" + getEnvWithDefault(imageURL, "nginx"), - "--image-url=" + getEnvWithDefault(imageURL, "nginx"), - "--test-with-device=" + getEnvWithDefault(testWithDevice, "false"), + "--report-dir=" + util.GetEnvWithDefault(resultsDirEnvKey, defaultResultsDir), + "--report-prefix=" + util.GetEnvWithDefault(reportPrefixEnvKey, defaultReportPrefix), + "--kubeconfig=" + util.GetEnvWithDefault(kubeConfigEnvKey, ""), + "--image-url=" + util.GetEnvWithDefault(imageURL, "nginx"), + "--test-with-device=" + util.GetEnvWithDefault(testWithDevice, "false"), } - if len(getEnvWithDefault(extraArgsEnvKey, "")) > 0 { - extraArgs = append(extraArgs, strings.Split(getEnvWithDefault(extraArgsEnvKey, ""), ",")...) + if len(util.GetEnvWithDefault(extraArgsEnvKey, "")) > 0 { + extraArgs = append(extraArgs, strings.Split(util.GetEnvWithDefault(extraArgsEnvKey, ""), ",")...) } var args []string args = append(args, ginkgoArgs...) - args = append(args, getEnvWithDefault(testBinEnvKey, defaultTestBinary)) + args = append(args, util.GetEnvWithDefault(testBinEnvKey, defaultTestBinary)) args = append(args, "--") args = append(args, extraArgs...) - cmd := exec.Command(getEnvWithDefault(ginkgoEnvKey, defaultGinkgoBinary), args...) + cmd := exec.Command(util.GetEnvWithDefault(ginkgoEnvKey, defaultGinkgoBinary), args...) cmd.Stdout = w cmd.Stderr = w return cmd, nil } - -func getEnvWithDefault(envKey, defaultValue string) string { - value := os.Getenv(envKey) - if len(value) == 0 { - return defaultValue - } - return value -} - -type Tests struct { - TestName string `yaml:"testname"` - CodeName string `yaml:"codename"` - Description string `yaml:"description"` - Release string `yaml:"release"` - File string `yaml:"file"` -} - -func skipCommands() ([]string, error) { - tests, err := skipCases() - if err != nil { - return nil, err - } - - var skipCommands []string - for _, test := range tests { - skipCommands = append(skipCommands, test.CodeName) - } - - return skipCommands, nil -} - -func skipCases() ([]Tests, error) { - data, err := Read("/testdata/edge_skip_case.yaml") - if err != nil { - return nil, fmt.Errorf("read skip test case err: %v", err) - } - - var skipTests []Tests - - if err := yaml.Unmarshal(data, &skipTests); err != nil { - return nil, fmt.Errorf("unmarshal skip test case err: %v", err) - } - - return skipTests, err -} - -func Read(filePath string) ([]byte, error) { - data, err := os.ReadFile(filePath) - if os.IsNotExist(err) { - // Not an error (yet), some other provider may have the file. - return nil, nil - } - return data, err -} - -func cmdInfo(cmd *exec.Cmd) string { - return fmt.Sprintf( - `Command env: %v -Run from directory: %v -Executable path: %v -Args (comma-delimited): %v`, cmd.Env, cmd.Dir, cmd.Path, strings.Join(cmd.Args, ","), - ) -} - -// tempTaints is temporarily added to center node when run kubeEdge conformance -// to make sure that all the pod created by conformance to run on the edge node -var tempTaints = &v1.Taint{ - Key: "node.kubeedge.io/conformance", - Value: "remove-when-completed", - Effect: v1.TaintEffectNoSchedule, -} - -var updateTaintBackoff = wait.Backoff{ - Steps: 5, - Duration: 100 * time.Millisecond, - Jitter: 1.0, -} - -// beforeRunConformance do prepare work before run conformance -func beforeRunConformance() error { - kubeClient, err := getKubeClient() - if err != nil { - return err - } - - nodeList, err := kubeClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - - for _, node := range nodeList.Items { - if isEdgeNode(node) { - continue - } - - err = addConformanceTaintOnNode(kubeClient, &node) - if err != nil { - return err - } - } - - return nil -} - -// afterRunConformance do clean work after conformance done -func afterRunConformance() error { - kubeClient, err := getKubeClient() - if err != nil { - return err - } - - nodeList, err := kubeClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return err - } - - for _, node := range nodeList.Items { - if isEdgeNode(node) { - continue - } - - err = deleteConformanceTaintOnNode(kubeClient, &node) - if err != nil { - log.Printf("failed delete taint for node:%v\n", node.Name) - } - } - - return nil -} - -func addConformanceTaintOnNode(c kubernetes.Interface, node *v1.Node) error { - newNode, updated := addTaint(node, tempTaints) - if !updated { - return nil - } - - return retry.RetryOnConflict(updateTaintBackoff, func() error { - return patchNodeTaints(c, node, newNode) - }) -} - -func deleteConformanceTaintOnNode(c kubernetes.Interface, node *v1.Node) error { - newNode, updated := removeTaint(node, tempTaints) - if !updated { - return nil - } - - return retry.RetryOnConflict(updateTaintBackoff, func() error { - return patchNodeTaints(c, node, newNode) - }) -} - -func isEdgeNode(node v1.Node) bool { - if node.Labels == nil { - return false - } - - _, ok := node.Labels[edgeNodeLabelKey] - return ok -} - -func getKubeClient() (kubernetes.Interface, error) { - configPath := getEnvWithDefault(kubeConfigEnvKey, "") - kubeConfig, err := clientcmd.BuildConfigFromFlags("", configPath) - if err != nil { - return nil, err - } - - kubeConfig.ContentType = runtime.ContentTypeProtobuf - kubeClient := kubernetes.NewForConfigOrDie(kubeConfig) - return kubeClient, nil -} - -func addTaint(node *v1.Node, taint *v1.Taint) (*v1.Node, bool) { - newNode := node.DeepCopy() - nodeTaints := newNode.Spec.Taints - - var newTaints []v1.Taint - for i := range nodeTaints { - if taint.MatchTaint(&nodeTaints[i]) { - log.Printf("taint already exist for node:%v\n", node.Name) - return node, false - } - - newTaints = append(newTaints, nodeTaints[i]) - } - - newTaints = append(newTaints, *taint) - newNode.Spec.Taints = newTaints - - return newNode, true -} - -func removeTaint(node *v1.Node, taintToDelete *v1.Taint) (*v1.Node, bool) { - newNode := node.DeepCopy() - nodeTaints := newNode.Spec.Taints - if len(nodeTaints) == 0 { - return newNode, false - } - - var newTaints []v1.Taint - deleted := false - for i := range nodeTaints { - if taintToDelete.MatchTaint(&nodeTaints[i]) { - deleted = true - continue - } - newTaints = append(newTaints, nodeTaints[i]) - } - - newNode.Spec.Taints = newTaints - - return newNode, deleted -} - -func patchNodeTaints(c kubernetes.Interface, oldNode *v1.Node, newNode *v1.Node) error { - oldData, err := json.Marshal(oldNode) - if err != nil { - return fmt.Errorf("failed to marshal old node %#v for node %q: %v", oldNode, oldNode.Name, err) - } - - newTaints := newNode.Spec.Taints - newNodeClone := oldNode.DeepCopy() - newNodeClone.Spec.Taints = newTaints - newData, err := json.Marshal(newNodeClone) - if err != nil { - return fmt.Errorf("failed to marshal new node %#v for node %q: %v", newNodeClone, oldNode.Name, err) - } - - patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{}) - if err != nil { - return fmt.Errorf("failed to create patch for node %q: %v", oldNode.Name, err) - } - - _, err = c.CoreV1().Nodes().Patch(context.TODO(), oldNode.Name, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}) - return err -} |
