cli: add embedded node config

If `config-path` is not passed, default configs are used according to
the set network. In VM CLI the default privnet config with InMemory db
is used.

Close #3450
Close #3459

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
This commit is contained in:
Ekaterina Pavlova 2024-06-27 13:47:18 +03:00
parent ce1edda3f2
commit a9abd84cc4
4 changed files with 91 additions and 18 deletions

View file

@ -201,7 +201,7 @@ func GetConfigFromContext(ctx *cli.Context) (config.Config, error) {
if len(configFile) != 0 { if len(configFile) != 0 {
return config.LoadFile(configFile, relativePath) return config.LoadFile(configFile, relativePath)
} }
var configPath = "./config" var configPath = config.DefaultConfigPath
if argCp := ctx.String("config-path"); argCp != "" { if argCp := ctx.String("config-path"); argCp != "" {
configPath = argCp configPath = argCp
} }

32
config/config_embed.go Normal file
View file

@ -0,0 +1,32 @@
// Package config contains embedded YAML configuration files for different network modes
// of the Neo N3 blockchain and for NeoFS mainnet and testnet networks.
package config
import (
_ "embed"
)
// MainNet is the Neo N3 mainnet configuration.
//
//go:embed protocol.mainnet.yml
var MainNet []byte
// TestNet is the Neo N3 testnet configuration.
//
//go:embed protocol.testnet.yml
var TestNet []byte
// PrivNet is the private network configuration.
//
//go:embed protocol.privnet.yml
var PrivNet []byte
// MainNetNeoFS is the mainnet NeoFS configuration.
//
//go:embed protocol.mainnet.neofs.yml
var MainNetNeoFS []byte
// TestNetNeoFS is the testnet NeoFS configuration.
//
//go:embed protocol.testnet.neofs.yml
var TestNetNeoFS []byte

View file

@ -6,8 +6,8 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"time"
"github.com/nspcc-dev/neo-go/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/config/netmode"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
@ -38,6 +38,8 @@ const (
// DefaultMaxRequestHeaderBytes is the maximum permitted size of the headers // DefaultMaxRequestHeaderBytes is the maximum permitted size of the headers
// in an HTTP request. // in an HTTP request.
DefaultMaxRequestHeaderBytes = http.DefaultMaxHeaderBytes DefaultMaxRequestHeaderBytes = http.DefaultMaxHeaderBytes
// DefaultConfigPath is the default path to the config directory.
DefaultConfigPath = "./config"
) )
// Version is the version of the node, set at the build time. // Version is the version of the node, set at the build time.
@ -76,22 +78,21 @@ func Load(path string, netMode netmode.Magic, relativePath ...string) (Config, e
// fixups if necessary. If relativePath is not empty, relative paths in the config will // fixups if necessary. If relativePath is not empty, relative paths in the config will
// be updated based on the provided relative path. // be updated based on the provided relative path.
func LoadFile(configPath string, relativePath ...string) (Config, error) { func LoadFile(configPath string, relativePath ...string) (Config, error) {
if _, err := os.Stat(configPath); os.IsNotExist(err) { var (
return Config{}, fmt.Errorf("config '%s' doesn't exist", configPath) configData []byte
} err error
config Config
configData, err := os.ReadFile(configPath) )
if err != nil { if _, err = os.Stat(configPath); os.IsNotExist(err) {
return Config{}, fmt.Errorf("unable to read config: %w", err) configData, err = getEmbeddedConfig(configPath)
} if err != nil {
return Config{}, err
config := Config{ }
ApplicationConfiguration: ApplicationConfiguration{ } else {
P2P: P2P{ configData, err = os.ReadFile(configPath)
PingInterval: 30 * time.Second, if err != nil {
PingTimeout: 90 * time.Second, return Config{}, fmt.Errorf("unable to read config: %w", err)
}, }
},
} }
decoder := yaml.NewDecoder(bytes.NewReader(configData)) decoder := yaml.NewDecoder(bytes.NewReader(configData))
decoder.KnownFields(true) decoder.KnownFields(true)
@ -111,6 +112,24 @@ func LoadFile(configPath string, relativePath ...string) (Config, error) {
return config, nil return config, nil
} }
// getEmbeddedConfig returns the embedded config based on the provided config path.
func getEmbeddedConfig(configPath string) ([]byte, error) {
switch configPath {
case fmt.Sprintf("%s/protocol.%s.yml", DefaultConfigPath, netmode.MainNet):
return config.MainNet, nil
case fmt.Sprintf("%s/protocol.%s.yml", DefaultConfigPath, netmode.TestNet):
return config.TestNet, nil
case fmt.Sprintf("%s/protocol.%s.yml", DefaultConfigPath, netmode.PrivNet):
return config.PrivNet, nil
case fmt.Sprintf("%s/protocol.mainnet.neofs.yml", DefaultConfigPath):
return config.MainNetNeoFS, nil
case fmt.Sprintf("%s/protocol.testnet.neofs.yml", DefaultConfigPath):
return config.TestNetNeoFS, nil
default:
return nil, fmt.Errorf("config '%s' doesn't exist and no matching embedded config was found", configPath)
}
}
// updateRelativePaths updates relative paths in the config structure based on the provided relative path. // updateRelativePaths updates relative paths in the config structure based on the provided relative path.
func updateRelativePaths(relativePath string, config *Config) { func updateRelativePaths(relativePath string, config *Config) {
updatePath := func(path *string) { updatePath := func(path *string) {

View file

@ -1,12 +1,16 @@
package config package config
import ( import (
"bytes"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/nspcc-dev/neo-go/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
) )
const testConfigPath = "./testdata/protocol.test.yml" const testConfigPath = "./testdata/protocol.test.yml"
@ -32,3 +36,21 @@ func TestUnknownConfigFields(t *testing.T) {
require.Contains(t, err.Error(), "field UnknownConfigurationField not found in type config.Config") require.Contains(t, err.Error(), "field UnknownConfigurationField not found in type config.Config")
}) })
} }
func TestLoadFileWithMissingDefaultConfigPath(t *testing.T) {
var cfgPrivNet Config
cfg, err := LoadFile(fmt.Sprintf("%s/protocol.%s.yml", DefaultConfigPath, netmode.PrivNet))
require.Nil(t, err)
decoder := yaml.NewDecoder(bytes.NewReader(config.PrivNet))
err = decoder.Decode(&cfgPrivNet)
require.NoError(t, err)
require.Equal(t, cfg, cfgPrivNet)
_, err = LoadFile(fmt.Sprintf("%s/protocol.%s.yml", os.TempDir(), netmode.PrivNet))
require.Error(t, err)
require.Contains(t, err.Error(), "doesn't exist and no matching embedded config was found")
_, err = LoadFile(fmt.Sprintf("%s/protocol.%s.yml", DefaultConfigPath, "aaa"))
require.Error(t, err)
require.Contains(t, err.Error(), "doesn't exist and no matching embedded config was found")
}