Merge pull request #14292 from tjungblu/debug_e2e

Add test name to e2e cluster members
This commit is contained in:
Sahdev Zala 2022-08-20 19:30:44 -04:00 committed by GitHub
commit 192d635da9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 23 deletions

View File

@ -33,6 +33,8 @@ import (
const DEBUG_LINES_TAIL = 40 const DEBUG_LINES_TAIL = 40
type ExpectProcess struct { type ExpectProcess struct {
name string
cmd *exec.Cmd cmd *exec.Cmd
fpty *os.File fpty *os.File
wg sync.WaitGroup wg sync.WaitGroup
@ -48,15 +50,16 @@ type ExpectProcess struct {
// NewExpect creates a new process for expect testing. // NewExpect creates a new process for expect testing.
func NewExpect(name string, arg ...string) (ep *ExpectProcess, err error) { func NewExpect(name string, arg ...string) (ep *ExpectProcess, err error) {
// if env[] is nil, use current system env // if env[] is nil, use current system env and the default command as name
return NewExpectWithEnv(name, arg, nil) return NewExpectWithEnv(name, arg, nil, name)
} }
// NewExpectWithEnv creates a new process with user defined env variables for expect testing. // NewExpectWithEnv creates a new process with user defined env variables for expect testing.
func NewExpectWithEnv(name string, args []string, env []string) (ep *ExpectProcess, err error) { func NewExpectWithEnv(name string, args []string, env []string, serverProcessConfigName string) (ep *ExpectProcess, err error) {
cmd := exec.Command(name, args...) cmd := exec.Command(name, args...)
cmd.Env = env cmd.Env = env
ep = &ExpectProcess{ ep = &ExpectProcess{
name: serverProcessConfigName,
cmd: cmd, cmd: cmd,
StopSignal: syscall.SIGTERM, StopSignal: syscall.SIGTERM,
} }
@ -72,6 +75,10 @@ func NewExpectWithEnv(name string, args []string, env []string) (ep *ExpectProce
return ep, nil return ep, nil
} }
func (ep *ExpectProcess) Pid() int {
return ep.cmd.Process.Pid
}
func (ep *ExpectProcess) read() { func (ep *ExpectProcess) read() {
defer ep.wg.Done() defer ep.wg.Done()
printDebugLines := os.Getenv("EXPECT_DEBUG") != "" printDebugLines := os.Getenv("EXPECT_DEBUG") != ""
@ -81,7 +88,7 @@ func (ep *ExpectProcess) read() {
ep.mu.Lock() ep.mu.Lock()
if l != "" { if l != "" {
if printDebugLines { if printDebugLines {
fmt.Printf("%s-%d: %s", ep.cmd.Path, ep.cmd.Process.Pid, l) fmt.Printf("%s (%s) (%d): %s", ep.cmd.Path, ep.name, ep.cmd.Process.Pid, l)
} }
ep.lines = append(ep.lines, l) ep.lines = append(ep.lines, l)
ep.count++ ep.count++

View File

@ -19,13 +19,15 @@ import (
"net/url" "net/url"
"os" "os"
"path" "path"
"regexp"
"strings" "strings"
"testing" "testing"
"time" "time"
"go.etcd.io/etcd/server/v3/etcdserver"
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zaptest" "go.uber.org/zap/zaptest"
"go.etcd.io/etcd/server/v3/etcdserver"
) )
const EtcdProcessBasePort = 20000 const EtcdProcessBasePort = 20000
@ -38,6 +40,9 @@ const (
ClientTLSAndNonTLS ClientTLSAndNonTLS
) )
// allow alphanumerics, underscores and dashes
var testNameCleanRegex = regexp.MustCompile(`[^a-zA-Z0-9 \-_]+`)
func NewConfigNoTLS() *EtcdProcessClusterConfig { func NewConfigNoTLS() *EtcdProcessClusterConfig {
return &EtcdProcessClusterConfig{ClusterSize: 3, return &EtcdProcessClusterConfig{ClusterSize: 3,
InitialToken: "new", InitialToken: "new",
@ -284,7 +289,8 @@ func (cfg *EtcdProcessClusterConfig) EtcdServerProcessConfigs(tb testing.TB) []*
} }
purl := url.URL{Scheme: cfg.PeerScheme(), Host: fmt.Sprintf("localhost:%d", port+1)} purl := url.URL{Scheme: cfg.PeerScheme(), Host: fmt.Sprintf("localhost:%d", port+1)}
name := fmt.Sprintf("test-%d", i)
name := fmt.Sprintf("%s-test-%d", testNameCleanRegex.ReplaceAllString(tb.Name(), ""), i)
dataDirPath := cfg.DataDirPath dataDirPath := cfg.DataDirPath
if cfg.DataDirPath == "" { if cfg.DataDirPath == "" {
dataDirPath = tb.TempDir() dataDirPath = tb.TempDir()

View File

@ -26,8 +26,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"go.etcd.io/etcd/pkg/v3/expect"
"go.uber.org/zap" "go.uber.org/zap"
"go.etcd.io/etcd/pkg/v3/expect"
) )
type proxyEtcdProcess struct { type proxyEtcdProcess struct {
@ -109,6 +110,7 @@ func (p *proxyEtcdProcess) Logs() LogsExpect {
type proxyProc struct { type proxyProc struct {
lg *zap.Logger lg *zap.Logger
name string
execPath string execPath string
args []string args []string
ep string ep string
@ -124,7 +126,7 @@ func (pp *proxyProc) start() error {
if pp.proc != nil { if pp.proc != nil {
panic("already started") panic("already started")
} }
proc, err := SpawnCmdWithLogger(pp.lg, append([]string{pp.execPath}, pp.args...), nil) proc, err := SpawnCmdWithLogger(pp.lg, append([]string{pp.execPath}, pp.args...), nil, pp.name)
if err != nil { if err != nil {
return err return err
} }
@ -188,6 +190,7 @@ func newProxyV2Proc(cfg *EtcdServerProcessConfig) *proxyV2Proc {
} }
return &proxyV2Proc{ return &proxyV2Proc{
proxyProc: proxyProc{ proxyProc: proxyProc{
name: cfg.Name,
lg: cfg.lg, lg: cfg.lg,
execPath: cfg.ExecPath, execPath: cfg.ExecPath,
args: append(args, cfg.TlsArgs...), args: append(args, cfg.TlsArgs...),
@ -251,6 +254,7 @@ func newProxyV3Proc(cfg *EtcdServerProcessConfig) *proxyV3Proc {
return &proxyV3Proc{ return &proxyV3Proc{
proxyProc{ proxyProc{
name: cfg.Name,
lg: cfg.lg, lg: cfg.lg,
execPath: cfg.ExecPath, execPath: cfg.ExecPath,
args: append(args, tlsArgs...), args: append(args, tlsArgs...),

View File

@ -19,9 +19,10 @@ import (
"net/url" "net/url"
"os" "os"
"go.uber.org/zap"
"go.etcd.io/etcd/client/pkg/v3/fileutil" "go.etcd.io/etcd/client/pkg/v3/fileutil"
"go.etcd.io/etcd/pkg/v3/expect" "go.etcd.io/etcd/pkg/v3/expect"
"go.uber.org/zap"
) )
var ( var (
@ -100,33 +101,33 @@ func (ep *EtcdServerProcess) Start() error {
panic("already started") panic("already started")
} }
ep.cfg.lg.Info("starting server...", zap.String("name", ep.cfg.Name)) ep.cfg.lg.Info("starting server...", zap.String("name", ep.cfg.Name))
proc, err := SpawnCmdWithLogger(ep.cfg.lg, append([]string{ep.cfg.ExecPath}, ep.cfg.Args...), ep.cfg.EnvVars) proc, err := SpawnCmdWithLogger(ep.cfg.lg, append([]string{ep.cfg.ExecPath}, ep.cfg.Args...), ep.cfg.EnvVars, ep.cfg.Name)
if err != nil { if err != nil {
return err return err
} }
ep.proc = proc ep.proc = proc
err = ep.waitReady() err = ep.waitReady()
if err == nil { if err == nil {
ep.cfg.lg.Info("started server.", zap.String("name", ep.cfg.Name)) ep.cfg.lg.Info("started server.", zap.String("name", ep.cfg.Name), zap.Int("pid", ep.proc.Pid()))
} }
return err return err
} }
func (ep *EtcdServerProcess) Restart() error { func (ep *EtcdServerProcess) Restart() error {
ep.cfg.lg.Info("restaring server...", zap.String("name", ep.cfg.Name)) ep.cfg.lg.Info("restarting server...", zap.String("name", ep.cfg.Name))
if err := ep.Stop(); err != nil { if err := ep.Stop(); err != nil {
return err return err
} }
ep.donec = make(chan struct{}) ep.donec = make(chan struct{})
err := ep.Start() err := ep.Start()
if err == nil { if err == nil {
ep.cfg.lg.Info("restared server", zap.String("name", ep.cfg.Name)) ep.cfg.lg.Info("restarted server", zap.String("name", ep.cfg.Name))
} }
return err return err
} }
func (ep *EtcdServerProcess) Stop() (err error) { func (ep *EtcdServerProcess) Stop() (err error) {
ep.cfg.lg.Info("stoping server...", zap.String("name", ep.cfg.Name)) ep.cfg.lg.Info("stopping server...", zap.String("name", ep.cfg.Name))
if ep == nil || ep.proc == nil { if ep == nil || ep.proc == nil {
return nil return nil
} }
@ -174,7 +175,7 @@ func (ep *EtcdServerProcess) Config() *EtcdServerProcessConfig { return ep.cfg }
func (ep *EtcdServerProcess) Logs() LogsExpect { func (ep *EtcdServerProcess) Logs() LogsExpect {
if ep.proc == nil { if ep.proc == nil {
ep.cfg.lg.Panic("Please grap logs before process is stopped") ep.cfg.lg.Panic("Please grab logs before process is stopped")
} }
return ep.proc return ep.proc
} }

View File

@ -15,10 +15,17 @@
package e2e package e2e
import ( import (
"go.etcd.io/etcd/pkg/v3/expect" "strings"
"go.uber.org/zap" "go.uber.org/zap"
"go.etcd.io/etcd/pkg/v3/expect"
) )
func SpawnCmd(args []string, envVars map[string]string) (*expect.ExpectProcess, error) { func SpawnCmd(args []string, envVars map[string]string) (*expect.ExpectProcess, error) {
return SpawnCmdWithLogger(zap.NewNop(), args, envVars) return SpawnNamedCmd(strings.Join(args, "_"), args, envVars)
}
func SpawnNamedCmd(processName string, args []string, envVars map[string]string) (*expect.ExpectProcess, error) {
return SpawnCmdWithLogger(zap.NewNop(), args, envVars, processName)
} }

View File

@ -21,13 +21,14 @@ import (
"os" "os"
"strings" "strings"
"go.etcd.io/etcd/pkg/v3/expect"
"go.uber.org/zap" "go.uber.org/zap"
"go.etcd.io/etcd/pkg/v3/expect"
) )
const noOutputLineCount = 0 // regular binaries emit no extra lines const noOutputLineCount = 0 // regular binaries emit no extra lines
func SpawnCmdWithLogger(lg *zap.Logger, args []string, envVars map[string]string) (*expect.ExpectProcess, error) { func SpawnCmdWithLogger(lg *zap.Logger, args []string, envVars map[string]string, name string) (*expect.ExpectProcess, error) {
wd, err := os.Getwd() wd, err := os.Getwd()
if err != nil { if err != nil {
return nil, err return nil, err
@ -35,9 +36,17 @@ func SpawnCmdWithLogger(lg *zap.Logger, args []string, envVars map[string]string
env := mergeEnvVariables(envVars) env := mergeEnvVariables(envVars)
if strings.HasSuffix(args[0], "/etcdctl3") { if strings.HasSuffix(args[0], "/etcdctl3") {
env = append(env, "ETCDCTL_API=3") env = append(env, "ETCDCTL_API=3")
lg.Info("spawning process with ETCDCTL_API=3", zap.Strings("args", args), zap.String("working-dir", wd), zap.Strings("environment-variables", env)) lg.Info("spawning process with ETCDCTL_API=3",
return expect.NewExpectWithEnv(CtlBinPath, args[1:], env) zap.Strings("args", args),
zap.String("working-dir", wd),
zap.String("name", name),
zap.Strings("environment-variables", env))
return expect.NewExpectWithEnv(CtlBinPath, args[1:], env, name)
} }
lg.Info("spawning process", zap.Strings("args", args), zap.String("working-dir", wd), zap.Strings("environment-variables", env)) lg.Info("spawning process",
return expect.NewExpectWithEnv(args[0], args[1:], env) zap.Strings("args", args),
zap.String("working-dir", wd),
zap.String("name", name),
zap.Strings("environment-variables", env))
return expect.NewExpectWithEnv(args[0], args[1:], env, name)
} }