Merge pull request #124288 from pohly/test-e2e-node-debugger

e2e node: debugger support
This commit is contained in:
Kubernetes Prow Robot
2024-04-22 08:43:27 -07:00
committed by GitHub
3 changed files with 74 additions and 8 deletions

View File

@@ -22,6 +22,7 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"k8s.io/kubernetes/test/e2e_node/builder"
@@ -32,12 +33,13 @@ import (
)
var buildDependencies = flag.Bool("build-dependencies", true, "If true, build all dependencies.")
var ginkgoFlags = flag.String("ginkgo-flags", "", "Space-separated list of arguments to pass to Ginkgo test runner.")
var testFlags = flag.String("test-flags", "", "Space-separated list of arguments to pass to node e2e test.")
var ginkgoFlags = flag.String("ginkgo-flags", "", "Space-separated list of arguments to pass to Ginkgo test runner, with shell-style quoting and escaping.")
var testFlags = flag.String("test-flags", "", "Space-separated list of arguments to pass to node e2e test, with shell-style quoting and escaping.")
var systemSpecName = flag.String("system-spec-name", "", fmt.Sprintf("The name of the system spec used for validating the image in the node conformance test. The specs are at %s. If unspecified, the default built-in spec (system.DefaultSpec) will be used.", system.SystemSpecPath))
var extraEnvs = flag.String("extra-envs", "", "The extra environment variables needed for node e2e tests. Format: a list of key=value pairs, e.g., env1=val1,env2=val2")
var runtimeConfig = flag.String("runtime-config", "", "The runtime configuration for the API server on the node e2e tests. Format: a list of key=value pairs, e.g., env1=val1,env2=val2")
var kubeletConfigFile = flag.String("kubelet-config-file", "", "The KubeletConfiguration file that should be applied to the kubelet")
var debugTool = flag.String("debug-tool", "", "'delve', 'dlv' or 'gdb': run e2e_node.test under that debugger")
func main() {
klog.InitFlags(nil)
@@ -56,10 +58,34 @@ func main() {
klog.Fatalf("Failed to get build output directory: %v", err)
}
klog.Infof("Got build output dir: %v", outputDir)
ginkgo := filepath.Join(outputDir, "ginkgo")
test := filepath.Join(outputDir, "e2e_node.test")
interactive := false
var cmd string
var args []string
switch *debugTool {
case "":
// No debugger, run gingko directly.
cmd = filepath.Join(outputDir, "ginkgo")
args = []string{*ginkgoFlags, test, "--"}
case "delve", "dlv":
dlv, err := exec.LookPath("dlv")
if err != nil {
klog.Fatalf("'dlv' not found: %v", err)
}
interactive = true
cmd = dlv
args = []string{"exec", test, "--", addGinkgoArgPrefix(*ginkgoFlags)}
case "gdb":
gdb, err := exec.LookPath("gdb")
if err != nil {
klog.Fatalf("'gdb' not found: %v", err)
}
interactive = true
cmd = gdb
args = []string{test, "--", addGinkgoArgPrefix(*ginkgoFlags)}
}
args := []string{*ginkgoFlags, test, "--", *testFlags, fmt.Sprintf("--runtime-config=%s", *runtimeConfig)}
args = append(args, *testFlags, fmt.Sprintf("--runtime-config=%s", *runtimeConfig))
if *systemSpecName != "" {
rootDir, err := utils.GetK8sRootDir()
if err != nil {
@@ -71,16 +97,40 @@ func main() {
if *kubeletConfigFile != "" {
args = append(args, fmt.Sprintf("--kubelet-config-file=\"%s\"", *kubeletConfigFile))
}
if err := runCommand(ginkgo, args...); err != nil {
if err := runCommand(interactive, cmd, args...); err != nil {
klog.Exitf("Test failed: %v", err)
}
return
}
func runCommand(name string, args ...string) error {
func addGinkgoArgPrefix(ginkgoFlags string) string {
// Warning, hack! This simplistic search/replace assumes that hyphens do not appear
// inside argument values.
//
// The right solution would be to use github.com/anmitsu/go-shlex to split
// the -ginkgo-flags and -test-flags strings into individual arguments, then invoke
// exec.Command with the resulting string slice instead of passing a single string
// to sh. But github.com/anmitsu/go-shlex is not a Kubernetes dependency and not
// worth adding.
ginkgoFlags = regexp.MustCompile(`(^| )--?`).ReplaceAllString(ginkgoFlags, `$1--ginkgo.`)
return ginkgoFlags
}
func runCommand(interactive bool, name string, args ...string) error {
klog.Infof("Running command: %v %v", name, strings.Join(args, " "))
// Using sh is necessary because the args are using POSIX quoting.
// sh has to parse that.
cmd := exec.Command("sudo", "sh", "-c", strings.Join(append([]string{name}, args...), " "))
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if interactive {
// stdin must be a console.
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdin
cmd.Stderr = os.Stdin
} else {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
}
return cmd.Run()
}