Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fuji local clusters #2309

Merged
merged 12 commits into from
Nov 14, 2024
13 changes: 13 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import (
"errors"
"fmt"
"os"
"os/signal"
"os/user"
"path/filepath"
"strings"
"syscall"
"time"

"github.com/ava-labs/avalanche-cli/cmd/backendcmd"
Expand All @@ -35,6 +37,7 @@ import (
"github.com/ava-labs/avalanche-cli/pkg/ux"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/perms"
ansi "github.com/k0kubun/go-ansi"

"github.com/spf13/cobra"
"go.uber.org/zap"
Expand Down Expand Up @@ -354,8 +357,18 @@ func initConfig() {
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
go handleInterrupt()
app = application.New()
rootCmd := NewRootCmd()
err := rootCmd.Execute()
cobrautils.HandleErrors(err)
}

func handleInterrupt() {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigChan
fmt.Println()
fmt.Println("received signal:", sig.String())
arturrez marked this conversation as resolved.
Show resolved Hide resolved
ansi.CursorShow()
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.22.8

require (
github.com/ava-labs/apm v1.0.0
github.com/ava-labs/avalanche-network-runner v1.8.4-0.20241023180457-5189aac811fb
github.com/ava-labs/avalanche-network-runner v1.8.4-0.20241102130338-5a17aecf300c
github.com/ava-labs/avalanchego v1.12.0-initial-poc.6
github.com/ava-labs/awm-relayer v1.4.1-0.20241014222901-4b34ab86afd0
github.com/ava-labs/coreth v0.13.8
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,10 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/ava-labs/apm v1.0.0 h1:6FwozH67hEkbWVsOXNZGexBy5KLpNeYucN9zcFUHv+Q=
github.com/ava-labs/apm v1.0.0/go.mod h1:TJL7pTlZNvQatsQPsLUtDHApEwVZ/qS7iSNtRFU83mc=
github.com/ava-labs/avalanche-network-runner v1.8.4-0.20241023180457-5189aac811fb h1:Fv5gyTIERypRVxtB4JSNoe16o45P0THySRDfrTuX0Dc=
github.com/ava-labs/avalanche-network-runner v1.8.4-0.20241023180457-5189aac811fb/go.mod h1:ASWB/CKJm8wVZUBp3DY0AV8jTBLCs01kzQz9GGwtzi8=
github.com/ava-labs/avalanche-network-runner v1.8.4-0.20241101154041-1be2d617875e h1:zafSQnLPTu4asqqrwg0fhSYUfOQ72VlmHzDfVOMXSsE=
github.com/ava-labs/avalanche-network-runner v1.8.4-0.20241101154041-1be2d617875e/go.mod h1:ASWB/CKJm8wVZUBp3DY0AV8jTBLCs01kzQz9GGwtzi8=
github.com/ava-labs/avalanche-network-runner v1.8.4-0.20241102130338-5a17aecf300c h1:KhTnFwU5i7HCkygPphAoj9ldFmaAqLi2diZBHilQGOQ=
github.com/ava-labs/avalanche-network-runner v1.8.4-0.20241102130338-5a17aecf300c/go.mod h1:ASWB/CKJm8wVZUBp3DY0AV8jTBLCs01kzQz9GGwtzi8=
github.com/ava-labs/avalanchego v1.12.0-initial-poc.6 h1:7Ijm0POq/NGX6jQG08BlOPfuHi9JYtDy4HylNAjel2A=
github.com/ava-labs/avalanchego v1.12.0-initial-poc.6/go.mod h1:gYlTU42Q4b29hzhUN22yclym5qwB3Si0jh4+LTn7DZM=
github.com/ava-labs/awm-relayer v1.4.1-0.20241014222901-4b34ab86afd0 h1:zsoK+TbXg/XOTXd+PXRrF6aGmpilcunfpcw/McPVBho=
Expand Down
2 changes: 2 additions & 0 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ const (
APIRequestLargeTimeout = 5 * time.Second
FastGRPCDialTimeout = 100 * time.Millisecond

FujiBootstrapTimeout = 5 * time.Minute

SSHServerStartTimeout = 1 * time.Minute
SSHScriptTimeout = 2 * time.Minute
SSHLongRunningScriptTimeout = 10 * time.Minute
Expand Down
10 changes: 10 additions & 0 deletions pkg/models/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package models

import (
"context"
"fmt"
"os"
"strings"
Expand Down Expand Up @@ -189,3 +190,12 @@ func (n *Network) HandlePublicNetworkSimulation() {
func (n *Network) Equals(n2 Network) bool {
return n.Kind == n2.Kind && n.Endpoint == n2.Endpoint
}

// Context for bootstrapping a partial synced Node
func (n *Network) BootstrappingContext() (context.Context, context.CancelFunc) {
timeout := constants.ANRRequestTimeout
if n.Kind == Fuji {
timeout = constants.FujiBootstrapTimeout
}
return context.WithTimeout(context.Background(), timeout)
}
39 changes: 37 additions & 2 deletions pkg/node/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ import (
"github.com/ava-labs/avalanche-network-runner/client"
anrutils "github.com/ava-labs/avalanche-network-runner/utils"
"github.com/ava-labs/avalanchego/api/info"
"github.com/ava-labs/avalanchego/config"
"github.com/ava-labs/avalanchego/ids"
avagoconstants "github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/avalanchego/vms/platformvm"
Expand Down Expand Up @@ -180,6 +182,27 @@ func StartLocalNode(
localDataExists = false
}

// set node configs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be cleaner for the caller of StartLocalNode to set the nodeConfig parameter properly for their use case rather than always overriding it with specific settings here. This allows the function to remain more general use for the future, for instance if we want to a start a local node that is going to become a primary network validator.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should also only ever serialize the config struct to start a node, rather than creating a Config instance, serializing it as JSON, then deserializing it to override certain keys, etc. Using the AvalancheGo defined type will be less error prone in the event of any future changes to the config structure.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed the Start() param to be a map[string]interface{} , and serialize it inside
I believe the avalanchego defined type (if it is the one define under avalanchego/node/config.go)
is not a good fit as we are just trying to set flags for the avalanchego command line, and it seems
not direct to map from the internal Config type to the desired flags. Unless I am missing something.

if nodeConfig == "" {
nodeConfig = "{}"
}
nodeConfig, err = utils.SetJSONKey(
nodeConfig,
config.PartialSyncPrimaryNetworkKey,
true,
)
if err != nil {
return err
}
nodeConfig, err = utils.SetJSONKey(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ProposerVMUseCurrentHeightKey required here? I think it shouldn't be necessary with the ACP-151. If it is still required, could you add a comment explaining why?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just included it because it was not included previously and reminded the flag was asked to be set.
Will just not include as I am not pretending it is still required.

nodeConfig,
config.ProposerVMUseCurrentHeightKey,
true,
)
if err != nil {
return err
}

// check if this is existing cluster
rootDir := app.GetLocalDir(clusterName)
pluginDir := filepath.Join(rootDir, "node1", "plugins")
Expand All @@ -194,6 +217,7 @@ func StartLocalNode(

ctx, cancel := utils.GetANRContext()
defer cancel()

// starts server
avalancheGoVersion := "latest"
if avalanchegoBinaryPath == "" {
Expand Down Expand Up @@ -255,14 +279,22 @@ func StartLocalNode(
} else {
ux.Logger.GreenCheckmarkToUser("Local cluster %s not found. Creating...", clusterName)
network := models.UndefinedNetwork
if useEtnaDevnet {
switch {
case useEtnaDevnet:
network = models.NewNetwork(
models.Devnet,
constants.EtnaDevnetNetworkID,
constants.EtnaDevnetEndpoint,
clusterName,
)
} else {
case globalNetworkFlags.UseFuji:
network = models.NewNetwork(
models.Fuji,
avagoconstants.FujiID,
constants.FujiAPIEndpoint,
clusterName,
)
default:
network, err = networkoptions.GetNetworkFromCmdLineFlags(
app,
"",
Expand Down Expand Up @@ -349,6 +381,9 @@ func StartLocalNode(
anrOpts = append(anrOpts, client.WithBootstrapNodeIPPortPairs(anrSettings.BootstrapIPs))
}

ctx, cancel = network.BootstrappingContext()
defer cancel()

ux.Logger.PrintToUser("Starting local avalanchego node using root: %s ...", rootDir)
spinSession := ux.NewUserSpinner()
spinner := spinSession.SpinToUser("Booting Network. Wait until healthy...")
Expand Down
19 changes: 19 additions & 0 deletions pkg/utils/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -589,3 +589,22 @@ func LogLevelToEmoji(logLevel string) (string, error) {
}
return levelEmoji, nil
}

// Set k=v in JSON string
// e.g., "track-subnets" is the key and value is "a,b,c".
func SetJSONKey(jsonBody string, k string, v interface{}) (string, error) {
arturrez marked this conversation as resolved.
Show resolved Hide resolved
var config map[string]interface{}
if err := json.Unmarshal([]byte(jsonBody), &config); err != nil {
return "", err
}
if v == nil {
delete(config, k)
} else {
config[k] = v
}
updatedJSON, err := json.Marshal(config)
if err != nil {
return "", err
}
return string(updatedJSON), nil
}
88 changes: 88 additions & 0 deletions pkg/utils/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
package utils

import (
"encoding/json"
"errors"
"reflect"
"testing"
"time"

"github.com/stretchr/testify/require"
)

func TestSplitKeyValueStringToMap(t *testing.T) {
Expand Down Expand Up @@ -293,3 +296,88 @@ func TestRetryFunction(t *testing.T) {
t.Errorf("Expected nil result, got %v", result)
}
}

func TestSetJSONKey(t *testing.T) {
tests := []struct {
desc string
json string
k string
v interface{}
shouldErr bool
out string
}{
{
desc: "invalid json",
json: "",
k: "k",
v: "v",
shouldErr: true,
out: "",
},
{
desc: "empty json",
json: "{}",
k: "k",
v: "v",
shouldErr: false,
out: "{\"k\": \"v\"}",
},
{
desc: "remove value",
json: "{\"k\": \"v\"}",
k: "k",
v: nil,
shouldErr: false,
out: "{}",
},
{
desc: "remove value on empty",
json: "{}",
k: "k",
v: nil,
shouldErr: false,
out: "{}",
},
{
desc: "remove value on multiple",
json: "{\"k\": \"v\", \"k2\": \"v2\"}",
k: "k",
v: nil,
shouldErr: false,
out: "{\"k2\": \"v2\"}",
},
{
desc: "change value",
json: "{\"k\": \"v\"}",
k: "k",
v: "newv",
shouldErr: false,
out: "{\"k\": \"newv\"}",
},
{
desc: "change value on multiple",
json: "{\"k\": \"v\", \"k2\": \"v2\"}",
k: "k",
v: "v1",
shouldErr: false,
out: "{\"k\": \"v1\", \"k2\": \"v2\"}",
},
}

require := require.New(t)
for _, test := range tests {
out, err := SetJSONKey(test.json, test.k, test.v)
if test.shouldErr {
require.Error(err, test.desc)
} else {
require.NoError(err, test.desc)
var expectedOutMap map[string]interface{}
var outMap map[string]interface{}
err := json.Unmarshal([]byte(out), &outMap)
require.NoError(err, test.desc)
err = json.Unmarshal([]byte(test.out), &expectedOutMap)
require.NoError(err, test.desc)
require.Equal(expectedOutMap, outMap, test.desc)
}
}
}
Loading