mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-12 04:30:04 +00:00
Warn if user is not using a supported platform (#7381)
* Add prereqs package * Incorporate prereq check into the clients * gazelle * gazelle fix * linter * Add tests * minor change in test * finish up tests * gazelle * error during platform detection does not cause client to fail fast Co-authored-by: dv8silencer <15720668+dv8silencer@users.noreply.github.com>
This commit is contained in:
parent
437bab7df0
commit
7d9a706cfa
beacon-chain/node
shared/prereq
slasher/node
validator/node
@ -34,6 +34,7 @@ go_library(
|
||||
"//shared/event:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/prereq:go_default_library",
|
||||
"//shared/prometheus:go_default_library",
|
||||
"//shared/sliceutil:go_default_library",
|
||||
"//shared/tracing:go_default_library",
|
||||
|
@ -41,6 +41,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/prereq"
|
||||
"github.com/prysmaticlabs/prysm/shared/prometheus"
|
||||
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/tracing"
|
||||
@ -91,6 +92,9 @@ func NewBeaconNode(cliCtx *cli.Context) (*BeaconNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Warn if user's platform is not supported
|
||||
prereq.WarnIfNotSupported(cliCtx.Context)
|
||||
|
||||
featureconfig.ConfigureBeaconChain(cliCtx)
|
||||
cmd.ConfigureBeaconChain(cliCtx)
|
||||
flags.ConfigureGlobalFlags(cliCtx)
|
||||
|
24
shared/prereq/BUILD.bazel
Normal file
24
shared/prereq/BUILD.bazel
Normal file
@ -0,0 +1,24 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_test")
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["prereq.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/shared/prereq",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["prereq_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
],
|
||||
)
|
108
shared/prereq/prereq.go
Normal file
108
shared/prereq/prereq.go
Normal file
@ -0,0 +1,108 @@
|
||||
package prereq
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type platform struct {
|
||||
os string
|
||||
arch string
|
||||
majorVersion int
|
||||
minorVersion int
|
||||
}
|
||||
|
||||
var (
|
||||
// execShellOutput has execShellOutputFunc as the default but can be changed for testing purposes.
|
||||
execShellOutput func(ctx context.Context, command string, args ...string) (string, error) = execShellOutputFunc
|
||||
runtimeOS = runtime.GOOS
|
||||
runtimeArch = runtime.GOARCH
|
||||
)
|
||||
|
||||
// execShellOutputFunc passes a command and args to exec.CommandContext and returns the result as a string
|
||||
func execShellOutputFunc(ctx context.Context, command string, args ...string) (string, error) {
|
||||
result, err := exec.CommandContext(ctx, command, args...).Output()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error in command execution")
|
||||
}
|
||||
return string(result), nil
|
||||
}
|
||||
|
||||
func getSupportedPlatforms() []platform {
|
||||
return []platform{
|
||||
{os: "linux", arch: "amd64"},
|
||||
{os: "linux", arch: "arm64"},
|
||||
{os: "darwin", arch: "amd64", majorVersion: 10, minorVersion: 14},
|
||||
{os: "windows", arch: "amd64"},
|
||||
}
|
||||
}
|
||||
|
||||
// parseVersion takes a string and splits it using sep separator, and outputs a slice of integers
|
||||
// corresponding to version numbers. If it cannot find num level of versions, it returns an error
|
||||
func parseVersion(input string, num int, sep string) ([]int, error) {
|
||||
var version = make([]int, num)
|
||||
components := strings.Split(input, sep)
|
||||
for i, component := range components {
|
||||
components[i] = strings.TrimSpace(component)
|
||||
}
|
||||
if len(components) < num {
|
||||
return nil, errors.New("insufficient information about version")
|
||||
}
|
||||
for i := range version {
|
||||
var err error
|
||||
version[i], err = strconv.Atoi(components[i])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error during conversion")
|
||||
}
|
||||
}
|
||||
return version, nil
|
||||
}
|
||||
|
||||
// meetsMinPlatformReqs returns true if the runtime matches any on the list of supported platforms
|
||||
func meetsMinPlatformReqs(ctx context.Context) (bool, error) {
|
||||
okPlatforms := getSupportedPlatforms()
|
||||
for _, platform := range okPlatforms {
|
||||
if runtimeOS == platform.os && runtimeArch == platform.arch {
|
||||
// If MacOS we make sure it meets the minimum version cutoff
|
||||
if runtimeOS == "darwin" {
|
||||
versionStr, err := execShellOutput(ctx, "uname", "-r")
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "error obtaining MacOS version")
|
||||
}
|
||||
version, err := parseVersion(versionStr, 2, ".")
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "error parsing version")
|
||||
}
|
||||
if version[0] != platform.majorVersion {
|
||||
return version[0] > platform.majorVersion, nil
|
||||
}
|
||||
if version[1] < platform.minorVersion {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
// Otherwise we have a match between runtime and our list of accepted platforms
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// WarnIfNotSupported warns if the user's platform is not supported or if it fails to detect user's platform
|
||||
func WarnIfNotSupported(ctx context.Context) {
|
||||
supported, err := meetsMinPlatformReqs(ctx)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to detect host platform: %v", err)
|
||||
return
|
||||
}
|
||||
if !supported {
|
||||
log.Warn("This platform is not supported. The following platforms are supported: Linux/AMD64," +
|
||||
" Linux/ARM64, Mac OS X/AMD64 (10.14+ only), and Windows/AMD64")
|
||||
}
|
||||
}
|
128
shared/prereq/prereq_test.go
Normal file
128
shared/prereq/prereq_test.go
Normal file
@ -0,0 +1,128 @@
|
||||
package prereq
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
func TestMeetsMinPlatformReqs(t *testing.T) {
|
||||
// Linux
|
||||
runtimeOS = "linux"
|
||||
runtimeArch = "amd64"
|
||||
meetsReqs, err := meetsMinPlatformReqs(context.Background())
|
||||
require.Equal(t, true, meetsReqs)
|
||||
require.NoError(t, err)
|
||||
runtimeArch = "arm64"
|
||||
meetsReqs, err = meetsMinPlatformReqs(context.Background())
|
||||
require.Equal(t, true, meetsReqs)
|
||||
require.NoError(t, err)
|
||||
// mips64 is not supported
|
||||
runtimeArch = "mips64"
|
||||
meetsReqs, err = meetsMinPlatformReqs(context.Background())
|
||||
require.Equal(t, false, meetsReqs)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Mac OS X
|
||||
// In this function we'll set the execShellOutput package variable to another function that will 'mock' the shell
|
||||
execShellOutput = func(ctx context.Context, command string, args ...string) (string, error) {
|
||||
return "", errors.New("error while running command")
|
||||
}
|
||||
runtimeOS = "darwin"
|
||||
runtimeArch = "amd64"
|
||||
meetsReqs, err = meetsMinPlatformReqs(context.Background())
|
||||
require.Equal(t, false, meetsReqs)
|
||||
require.ErrorContains(t, "error obtaining MacOS version", err)
|
||||
|
||||
// Insufficient version
|
||||
execShellOutput = func(ctx context.Context, command string, args ...string) (string, error) {
|
||||
return "10.4", nil
|
||||
}
|
||||
meetsReqs, err = meetsMinPlatformReqs(context.Background())
|
||||
require.Equal(t, false, meetsReqs)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Just-sufficient older version
|
||||
execShellOutput = func(ctx context.Context, command string, args ...string) (string, error) {
|
||||
return "10.14", nil
|
||||
}
|
||||
meetsReqs, err = meetsMinPlatformReqs(context.Background())
|
||||
require.Equal(t, true, meetsReqs)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Sufficient newer version
|
||||
execShellOutput = func(ctx context.Context, command string, args ...string) (string, error) {
|
||||
return "10.15.7", nil
|
||||
}
|
||||
meetsReqs, err = meetsMinPlatformReqs(context.Background())
|
||||
require.Equal(t, true, meetsReqs)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Handling abnormal response
|
||||
execShellOutput = func(ctx context.Context, command string, args ...string) (string, error) {
|
||||
return "tiger.lion", nil
|
||||
}
|
||||
meetsReqs, err = meetsMinPlatformReqs(context.Background())
|
||||
require.Equal(t, false, meetsReqs)
|
||||
require.ErrorContains(t, "error parsing version", err)
|
||||
|
||||
// Windows
|
||||
runtimeOS = "windows"
|
||||
runtimeArch = "amd64"
|
||||
meetsReqs, err = meetsMinPlatformReqs(context.Background())
|
||||
require.Equal(t, true, meetsReqs)
|
||||
require.NoError(t, err)
|
||||
runtimeArch = "arm64"
|
||||
meetsReqs, err = meetsMinPlatformReqs(context.Background())
|
||||
require.Equal(t, false, meetsReqs)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestParseVersion(t *testing.T) {
|
||||
version, err := parseVersion("1.2.3", 3, ".")
|
||||
require.DeepEqual(t, version, []int{1, 2, 3})
|
||||
require.NoError(t, err)
|
||||
|
||||
version, err = parseVersion("6 .7 . 8 ", 3, ".")
|
||||
require.DeepEqual(t, version, []int{6, 7, 8})
|
||||
require.NoError(t, err)
|
||||
|
||||
version, err = parseVersion("10,3,5,6", 4, ",")
|
||||
require.DeepEqual(t, version, []int{10, 3, 5, 6})
|
||||
require.NoError(t, err)
|
||||
|
||||
version, err = parseVersion("4;6;8;10;11", 3, ";")
|
||||
require.DeepEqual(t, version, []int{4, 6, 8})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = parseVersion("10.11", 3, ".")
|
||||
require.ErrorContains(t, "insufficient information about version", err)
|
||||
}
|
||||
|
||||
func TestWarnIfNotSupported(t *testing.T) {
|
||||
runtimeOS = "linux"
|
||||
runtimeArch = "amd64"
|
||||
hook := logTest.NewGlobal()
|
||||
WarnIfNotSupported(context.Background())
|
||||
require.LogsDoNotContain(t, hook, "Failed to detect host platform")
|
||||
require.LogsDoNotContain(t, hook, "platform is not supported")
|
||||
|
||||
execShellOutput = func(ctx context.Context, command string, args ...string) (string, error) {
|
||||
return "tiger.lion", nil
|
||||
}
|
||||
runtimeOS = "darwin"
|
||||
runtimeArch = "amd64"
|
||||
hook = logTest.NewGlobal()
|
||||
WarnIfNotSupported(context.Background())
|
||||
require.LogsContain(t, hook, "Failed to detect host platform")
|
||||
require.LogsContain(t, hook, "error parsing version")
|
||||
|
||||
runtimeOS = "falseOs"
|
||||
runtimeArch = "falseArch"
|
||||
hook = logTest.NewGlobal()
|
||||
WarnIfNotSupported(context.Background())
|
||||
require.LogsContain(t, hook, "platform is not supported")
|
||||
}
|
@ -13,6 +13,7 @@ go_library(
|
||||
"//shared/event:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/prereq:go_default_library",
|
||||
"//shared/prometheus:go_default_library",
|
||||
"//shared/tracing:go_default_library",
|
||||
"//shared/version:go_default_library",
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/prereq"
|
||||
"github.com/prysmaticlabs/prysm/shared/prometheus"
|
||||
"github.com/prysmaticlabs/prysm/shared/tracing"
|
||||
"github.com/prysmaticlabs/prysm/shared/version"
|
||||
@ -64,6 +65,9 @@ func NewSlasherNode(cliCtx *cli.Context) (*SlasherNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Warn if user's platform is not supported
|
||||
prereq.WarnIfNotSupported(cliCtx.Context)
|
||||
|
||||
if cliCtx.Bool(flags.EnableHistoricalDetectionFlag.Name) {
|
||||
// Set the max RPC size to 4096 as configured by --historical-slasher-node for optimal historical detection.
|
||||
cmdConfig := cmd.Get()
|
||||
|
@ -28,6 +28,7 @@ go_library(
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/fileutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/prereq:go_default_library",
|
||||
"//shared/prometheus:go_default_library",
|
||||
"//shared/tracing:go_default_library",
|
||||
"//shared/version:go_default_library",
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/fileutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/prereq"
|
||||
"github.com/prysmaticlabs/prysm/shared/prometheus"
|
||||
"github.com/prysmaticlabs/prysm/shared/tracing"
|
||||
"github.com/prysmaticlabs/prysm/shared/version"
|
||||
@ -71,6 +72,9 @@ func NewValidatorClient(cliCtx *cli.Context) (*ValidatorClient, error) {
|
||||
}
|
||||
logrus.SetLevel(level)
|
||||
|
||||
// Warn if user's platform is not supported
|
||||
prereq.WarnIfNotSupported(cliCtx.Context)
|
||||
|
||||
registry := shared.NewServiceRegistry()
|
||||
ValidatorClient := &ValidatorClient{
|
||||
cliCtx: cliCtx,
|
||||
|
Loading…
Reference in New Issue
Block a user