From 89da5d1ef55431517b1fb48466bd2ef55982fdaa Mon Sep 17 00:00:00 2001 From: Victor Farazdagi Date: Wed, 24 Mar 2021 23:55:12 +0300 Subject: [PATCH] E2E refactoring: bootnode (#8659) * BeaconNode * types/types.go * BootNode * gofmt * remove unused argument * remove redundant comment * add deprecation comment * types comment Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> --- endtoend/components/BUILD.bazel | 3 + endtoend/components/beacon_node.go | 61 ------------ endtoend/components/boot_node.go | 146 +++++++++++++++++++++++++++++ endtoend/components/log.go | 11 +++ endtoend/types/types.go | 10 ++ 5 files changed, 170 insertions(+), 61 deletions(-) create mode 100644 endtoend/components/boot_node.go create mode 100644 endtoend/components/log.go diff --git a/endtoend/components/BUILD.bazel b/endtoend/components/BUILD.bazel index bbed539f08..91574b4268 100644 --- a/endtoend/components/BUILD.bazel +++ b/endtoend/components/BUILD.bazel @@ -5,7 +5,9 @@ go_library( testonly = True, srcs = [ "beacon_node.go", + "boot_node.go", "eth1.go", + "log.go", "slasher.go", "validator.go", ], @@ -26,6 +28,7 @@ go_library( "@com_github_ethereum_go_ethereum//ethclient:go_default_library", "@com_github_ethereum_go_ethereum//rpc:go_default_library", "@com_github_pkg_errors//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", "@io_bazel_rules_go//go/tools/bazel:go_default_library", ], ) diff --git a/endtoend/components/beacon_node.go b/endtoend/components/beacon_node.go index aa7b083612..15e67bce3e 100644 --- a/endtoend/components/beacon_node.go +++ b/endtoend/components/beacon_node.go @@ -4,7 +4,6 @@ package components import ( "fmt" - "io/ioutil" "os/exec" "strings" "testing" @@ -72,63 +71,3 @@ func StartNewBeaconNode(t *testing.T, config *types.E2EConfig, index int, enr st t.Fatalf("could not find multiaddr for node %d, this means the node had issues starting: %v", index, err) } } - -// StartBootnode starts a bootnode and returns its ENR. -func StartBootnode(t *testing.T) string { - binaryPath, found := bazel.FindBinary("tools/bootnode", "bootnode") - if !found { - t.Log(binaryPath) - t.Fatal("boot node binary not found") - } - - stdOutFile, err := helpers.DeleteAndCreateFile(e2e.TestParams.LogPath, e2e.BootNodeLogFileName) - if err != nil { - t.Fatal(err) - } - - args := []string{ - fmt.Sprintf("--log-file=%s", stdOutFile.Name()), - fmt.Sprintf("--discv5-port=%d", e2e.TestParams.BootNodePort), - fmt.Sprintf("--metrics-port=%d", e2e.TestParams.BootNodePort+20), - "--debug", - } - - cmd := exec.Command(binaryPath, args...) - cmd.Stdout = stdOutFile - cmd.Stderr = stdOutFile - t.Logf("Starting boot node with flags: %s", strings.Join(args[1:], " ")) - if err = cmd.Start(); err != nil { - t.Fatalf("Failed to start beacon node: %v", err) - } - - if err = helpers.WaitForTextInFile(stdOutFile, "Running bootnode"); err != nil { - t.Fatalf("could not find enr for bootnode, this means the bootnode had issues starting: %v", err) - } - - enr, err := enrFromLogFile(stdOutFile.Name()) - if err != nil { - t.Fatalf("could not get enr for bootnode: %v", err) - } - - return enr -} - -func enrFromLogFile(name string) (string, error) { - byteContent, err := ioutil.ReadFile(name) - if err != nil { - return "", err - } - contents := string(byteContent) - - searchText := "Running bootnode: " - startIdx := strings.Index(contents, searchText) - if startIdx == -1 { - return "", fmt.Errorf("did not find ENR text in %s", contents) - } - startIdx += len(searchText) - endIdx := strings.Index(contents[startIdx:], " prefix=bootnode") - if endIdx == -1 { - return "", fmt.Errorf("did not find ENR text in %s", contents) - } - return contents[startIdx : startIdx+endIdx-1], nil -} diff --git a/endtoend/components/boot_node.go b/endtoend/components/boot_node.go new file mode 100644 index 0000000000..374ebe10de --- /dev/null +++ b/endtoend/components/boot_node.go @@ -0,0 +1,146 @@ +package components + +import ( + "context" + "errors" + "fmt" + "io/ioutil" + "os/exec" + "strings" + "testing" + + "github.com/bazelbuild/rules_go/go/tools/bazel" + "github.com/prysmaticlabs/prysm/endtoend/helpers" + e2e "github.com/prysmaticlabs/prysm/endtoend/params" + e2etypes "github.com/prysmaticlabs/prysm/endtoend/types" +) + +var _ e2etypes.ComponentRunner = (*BootNode)(nil) + +// BootNode represents boot node. +type BootNode struct { + e2etypes.ComponentRunner + started chan struct{} + enr string +} + +// NewBootNode creates and returns boot node. +func NewBootNode() *BootNode { + return &BootNode{ + started: make(chan struct{}, 1), + } +} + +// ENR exposes node's ENR. +func (node *BootNode) ENR() string { + return node.enr +} + +// StartBootnode starts a bootnode blocks up until ctx is cancelled. +func (node *BootNode) Start(ctx context.Context) error { + binaryPath, found := bazel.FindBinary("tools/bootnode", "bootnode") + if !found { + log.Info(binaryPath) + return errors.New("boot node binary not found") + } + + stdOutFile, err := helpers.DeleteAndCreateFile(e2e.TestParams.LogPath, e2e.BootNodeLogFileName) + if err != nil { + return err + } + + args := []string{ + fmt.Sprintf("--log-file=%s", stdOutFile.Name()), + fmt.Sprintf("--discv5-port=%d", e2e.TestParams.BootNodePort), + fmt.Sprintf("--metrics-port=%d", e2e.TestParams.BootNodePort+20), + "--debug", + } + + cmd := exec.CommandContext(ctx, binaryPath, args...) + cmd.Stdout = stdOutFile + cmd.Stderr = stdOutFile + log.Infof("Starting boot node with flags: %s", strings.Join(args[1:], " ")) + if err = cmd.Start(); err != nil { + return fmt.Errorf("failed to start beacon node: %w", err) + } + + if err = helpers.WaitForTextInFile(stdOutFile, "Running bootnode"); err != nil { + return fmt.Errorf("could not find enr for bootnode, this means the bootnode had issues starting: %w", err) + } + + node.enr, err = enrFromLogFile(stdOutFile.Name()) + if err != nil { + return fmt.Errorf("could not get enr for bootnode: %w", err) + } + + // Mark node as ready. + close(node.started) + + return cmd.Wait() +} + +// Started checks whether a boot node is started and ready to be queried. +func (node *BootNode) Started() <-chan struct{} { + return node.started +} + +// StartBootnode starts a bootnode and returns its ENR. +// Deprecated: this method will be removed once BootNode component is used. +func StartBootnode(t *testing.T) string { + binaryPath, found := bazel.FindBinary("tools/bootnode", "bootnode") + if !found { + t.Log(binaryPath) + t.Fatal("boot node binary not found") + } + + stdOutFile, err := helpers.DeleteAndCreateFile(e2e.TestParams.LogPath, e2e.BootNodeLogFileName) + if err != nil { + t.Fatal(err) + } + + args := []string{ + fmt.Sprintf("--log-file=%s", stdOutFile.Name()), + fmt.Sprintf("--discv5-port=%d", e2e.TestParams.BootNodePort), + fmt.Sprintf("--metrics-port=%d", e2e.TestParams.BootNodePort+20), + "--debug", + } + + cmd := exec.Command(binaryPath, args...) + cmd.Stdout = stdOutFile + cmd.Stderr = stdOutFile + t.Logf("Starting boot node with flags: %s", strings.Join(args[1:], " ")) + if err = cmd.Start(); err != nil { + t.Fatalf("Failed to start beacon node: %v", err) + } + + if err = helpers.WaitForTextInFile(stdOutFile, "Running bootnode"); err != nil { + t.Fatalf("could not find enr for bootnode, this means the bootnode had issues starting: %v", err) + } + + enr, err := enrFromLogFile(stdOutFile.Name()) + if err != nil { + t.Fatalf("could not get enr for bootnode: %v", err) + } + + return enr +} + +func enrFromLogFile(name string) (string, error) { + byteContent, err := ioutil.ReadFile(name) + if err != nil { + return "", err + } + contents := string(byteContent) + + searchText := "Running bootnode: " + startIdx := strings.Index(contents, searchText) + if startIdx == -1 { + return "", fmt.Errorf("did not find ENR text in %s", contents) + } + startIdx += len(searchText) + endIdx := strings.Index(contents[startIdx:], " prefix=bootnode") + if endIdx == -1 { + return "", fmt.Errorf("did not find ENR text in %s", contents) + } + return contents[startIdx : startIdx+endIdx-1], nil +} diff --git a/endtoend/components/log.go b/endtoend/components/log.go new file mode 100644 index 0000000000..1c3133b4b0 --- /dev/null +++ b/endtoend/components/log.go @@ -0,0 +1,11 @@ +package components + +import ( + "github.com/sirupsen/logrus" +) + +var log = logrus.WithField("prefix", "components") + +func init() { + logrus.SetReportCaller(true) +} diff --git a/endtoend/types/types.go b/endtoend/types/types.go index 1188cc6ecb..8431e70153 100644 --- a/endtoend/types/types.go +++ b/endtoend/types/types.go @@ -3,6 +3,8 @@ package types import ( + "context" + types "github.com/prysmaticlabs/eth2-types" "google.golang.org/grpc" ) @@ -26,3 +28,11 @@ type Evaluator struct { Policy func(currentEpoch types.Epoch) bool Evaluation func(conn ...*grpc.ClientConn) error // A variable amount of conns is allowed to be passed in for evaluations to check all nodes if needed. } + +// ComponentRunner defines an interface via which E2E component's configuration, execution and termination is managed. +type ComponentRunner interface { + // Start starts a component. + Start(ctx context.Context) error + // Started checks whether an underlying component is started and ready to be queried. + Started() <-chan struct{} +}