Skip to content

Commit ddeec15

Browse files
committed
[tmpnet] Avoid serializing the node data directory
This is intended to simplify usage by CLI.
1 parent 0ccb028 commit ddeec15

File tree

4 files changed

+66
-98
lines changed

4 files changed

+66
-98
lines changed

tests/fixture/tmpnet/network.go

+20-30
Original file line numberDiff line numberDiff line change
@@ -504,23 +504,22 @@ func (n *Network) RestartNode(ctx context.Context, log logging.Logger, node *Nod
504504

505505
// Stops all nodes in the network.
506506
func (n *Network) Stop(ctx context.Context) error {
507-
// Target all nodes, including the ephemeral ones
508-
nodes, err := ReadNodes(n, true /* includeEphemeral */)
509-
if err != nil {
507+
// Ensure the node state is up-to-date
508+
if err := n.readNodes(); err != nil {
510509
return err
511510
}
512511

513512
var errs []error
514513

515514
// Initiate stop on all nodes
516-
for _, node := range nodes {
515+
for _, node := range n.Nodes {
517516
if err := node.InitiateStop(ctx); err != nil {
518517
errs = append(errs, fmt.Errorf("failed to stop node %s: %w", node.NodeID, err))
519518
}
520519
}
521520

522521
// Wait for stop to complete on all nodes
523-
for _, node := range nodes {
522+
for _, node := range n.Nodes {
524523
if err := node.WaitForStopped(ctx); err != nil {
525524
errs = append(errs, fmt.Errorf("failed to wait for node %s to stop: %w", node.NodeID, err))
526525
}
@@ -554,16 +553,6 @@ func (n *Network) EnsureNodeConfig(node *Node) error {
554553
return err
555554
}
556555

557-
if len(n.Dir) > 0 {
558-
// Ensure the node's data dir is configured
559-
dataDir := node.GetDataDir()
560-
if len(dataDir) == 0 {
561-
// NodeID will have been set by EnsureKeys
562-
dataDir = filepath.Join(n.Dir, node.NodeID.String())
563-
node.Flags[config.DataDirKey] = dataDir
564-
}
565-
}
566-
567556
return nil
568557
}
569558

@@ -768,16 +757,13 @@ func (n *Network) GetNodeURIs() []NodeURI {
768757
// collecting the bootstrap details for restarting a node).
769758
// For consumption outside of avalanchego. Needs to be kept exported.
770759
func (n *Network) GetBootstrapIPsAndIDs(skippedNode *Node) ([]string, []string, error) {
771-
// Collect staking addresses of non-ephemeral nodes for use in bootstrapping a node
772-
nodes, err := ReadNodes(n, false /* includeEphemeral */)
773-
if err != nil {
774-
return nil, nil, fmt.Errorf("failed to read network's nodes: %w", err)
775-
}
776-
var (
777-
bootstrapIPs = make([]string, 0, len(nodes))
778-
bootstrapIDs = make([]string, 0, len(nodes))
779-
)
780-
for _, node := range nodes {
760+
bootstrapIPs := []string{}
761+
bootstrapIDs := []string{}
762+
for _, node := range n.Nodes {
763+
if node.IsEphemeral {
764+
// Ephemeral nodes are not guaranteed to stay running
765+
continue
766+
}
781767
if skippedNode != nil && node.NodeID == skippedNode.NodeID {
782768
continue
783769
}
@@ -940,12 +926,16 @@ func (n *Network) writeNodeFlags(log logging.Logger, node *Node) error {
940926
// Only configure the plugin dir with a non-empty value to ensure the use of
941927
// the default value (`[datadir]/plugins`) when no plugin dir is configured.
942928
processConfig := node.getRuntimeConfig().Process
943-
if processConfig != nil && len(processConfig.PluginDir) > 0 {
944-
// Ensure the plugin directory exists or the node will fail to start
945-
if err := os.MkdirAll(processConfig.PluginDir, perms.ReadWriteExecute); err != nil {
946-
return fmt.Errorf("failed to create plugin dir: %w", err)
929+
if processConfig != nil {
930+
if len(processConfig.PluginDir) > 0 {
931+
// Ensure the plugin directory exists or the node will fail to start
932+
if err := os.MkdirAll(processConfig.PluginDir, perms.ReadWriteExecute); err != nil {
933+
return fmt.Errorf("failed to create plugin dir: %w", err)
934+
}
935+
flags.SetDefault(config.PluginDirKey, processConfig.PluginDir)
947936
}
948-
flags.SetDefault(config.PluginDirKey, processConfig.PluginDir)
937+
938+
flags.SetDefault(config.DataDirKey, node.GetDataDir())
949939
}
950940

951941
// Set the network and tmpnet defaults last to ensure they can be overridden

tests/fixture/tmpnet/network_config.go

+25-3
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,35 @@ func (n *Network) readNetwork() error {
5757
return n.readConfig()
5858
}
5959

60-
// Read the non-ephemeral nodes associated with the network from disk.
60+
// Read the nodes associated with the network from disk.
6161
func (n *Network) readNodes() error {
62-
nodes, err := ReadNodes(n, false /* includeEphemeral */)
62+
nodes := []*Node{}
63+
64+
// Node configuration is stored in child directories
65+
entries, err := os.ReadDir(n.Dir)
6366
if err != nil {
64-
return err
67+
return fmt.Errorf("failed to read dir: %w", err)
6568
}
69+
for _, entry := range entries {
70+
if !entry.IsDir() {
71+
continue
72+
}
73+
74+
node := NewNode()
75+
dataDir := filepath.Join(n.Dir, entry.Name())
76+
err := node.Read(n, dataDir)
77+
if errors.Is(err, os.ErrNotExist) {
78+
// If no config file exists, assume this is not the path of a node
79+
continue
80+
} else if err != nil {
81+
return err
82+
}
83+
84+
nodes = append(nodes, node)
85+
}
86+
6687
n.Nodes = nodes
88+
6789
return nil
6890
}
6991

tests/fixture/tmpnet/node.go

+5-56
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,15 @@ package tmpnet
66
import (
77
"context"
88
"encoding/base64"
9-
"errors"
109
"fmt"
1110
"io"
1211
"net"
1312
"net/http"
1413
"net/netip"
15-
"os"
1614
"path/filepath"
1715
"strings"
1816
"time"
1917

20-
"github.com/spf13/cast"
21-
2218
"github.com/ava-labs/avalanchego/config"
2319
"github.com/ava-labs/avalanchego/ids"
2420
"github.com/ava-labs/avalanchego/staking"
@@ -91,17 +87,15 @@ type Node struct {
9187
}
9288

9389
// Initializes a new node with only the data dir set
94-
func NewNode(dataDir string) *Node {
90+
func NewNode() *Node {
9591
return &Node{
96-
Flags: FlagsMap{
97-
config.DataDirKey: dataDir,
98-
},
92+
Flags: FlagsMap{},
9993
}
10094
}
10195

10296
// Initializes an ephemeral node using the provided config flags
10397
func NewEphemeralNode(flags FlagsMap) *Node {
104-
node := NewNode("")
98+
node := NewNode()
10599
node.Flags = flags
106100
node.IsEphemeral = true
107101

@@ -112,7 +106,7 @@ func NewEphemeralNode(flags FlagsMap) *Node {
112106
func NewNodesOrPanic(count int) []*Node {
113107
nodes := make([]*Node, count)
114108
for i := range nodes {
115-
node := NewNode("")
109+
node := NewNode()
116110
if err := node.EnsureKeys(); err != nil {
117111
panic(err)
118112
}
@@ -121,51 +115,6 @@ func NewNodesOrPanic(count int) []*Node {
121115
return nodes
122116
}
123117

124-
// Reads a node's configuration from the specified directory.
125-
func ReadNode(dataDir string) (*Node, error) {
126-
node := NewNode(dataDir)
127-
return node, node.Read()
128-
}
129-
130-
// Reads nodes from the specified network directory.
131-
func ReadNodes(network *Network, includeEphemeral bool) ([]*Node, error) {
132-
nodes := []*Node{}
133-
134-
// Node configuration is stored in child directories
135-
entries, err := os.ReadDir(network.Dir)
136-
if err != nil {
137-
return nil, fmt.Errorf("failed to read dir: %w", err)
138-
}
139-
for _, entry := range entries {
140-
if !entry.IsDir() {
141-
continue
142-
}
143-
144-
nodeDir := filepath.Join(network.Dir, entry.Name())
145-
node, err := ReadNode(nodeDir)
146-
if errors.Is(err, os.ErrNotExist) {
147-
// If no config file exists, assume this is not the path of a node
148-
continue
149-
} else if err != nil {
150-
return nil, err
151-
}
152-
153-
if !includeEphemeral && node.IsEphemeral {
154-
continue
155-
}
156-
157-
if err := node.EnsureNodeID(); err != nil {
158-
return nil, fmt.Errorf("failed to ensure NodeID: %w", err)
159-
}
160-
161-
node.network = network
162-
163-
nodes = append(nodes, node)
164-
}
165-
166-
return nodes, nil
167-
}
168-
169118
// Retrieves the runtime for the node.
170119
func (n *Node) getRuntime() NodeRuntime {
171120
if n.runtime == nil {
@@ -211,7 +160,7 @@ func (n *Node) readState() error {
211160
}
212161

213162
func (n *Node) GetDataDir() string {
214-
return cast.ToString(n.Flags[config.DataDirKey])
163+
return filepath.Join(n.network.Dir, n.NodeID.String())
215164
}
216165

217166
func (n *Node) GetLocalURI(ctx context.Context) (string, func(), error) {

tests/fixture/tmpnet/node_config.go

+16-9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ import (
1717
// The Node type is defined in this file node_config.go
1818
// (reading/writing configuration) and node.go (orchestration).
1919

20+
func getNodeConfigPath(dataDir string) string {
21+
return filepath.Join(dataDir, defaultConfigFilename)
22+
}
23+
2024
// For consumption outside of avalanchego. Needs to be kept exported.
2125
func (n *Node) GetFlagsPath() string {
2226
return filepath.Join(n.GetDataDir(), "flags.json")
@@ -33,12 +37,9 @@ func (n *Node) writeFlags(flags FlagsMap) error {
3337
return nil
3438
}
3539

36-
func (n *Node) getConfigPath() string {
37-
return filepath.Join(n.GetDataDir(), defaultConfigFilename)
38-
}
39-
40-
func (n *Node) readConfig() error {
41-
bytes, err := os.ReadFile(n.getConfigPath())
40+
func (n *Node) readConfig(dataDir string) error {
41+
configPath := getNodeConfigPath(dataDir)
42+
bytes, err := os.ReadFile(configPath)
4243
if err != nil {
4344
return fmt.Errorf("failed to read node config: %w", err)
4445
}
@@ -64,14 +65,20 @@ func (n *Node) writeConfig() error {
6465
if err != nil {
6566
return fmt.Errorf("failed to marshal node config: %w", err)
6667
}
67-
if err := os.WriteFile(n.getConfigPath(), bytes, perms.ReadWrite); err != nil {
68+
configPath := getNodeConfigPath(n.GetDataDir())
69+
if err := os.WriteFile(configPath, bytes, perms.ReadWrite); err != nil {
6870
return fmt.Errorf("failed to write node config: %w", err)
6971
}
7072
return nil
7173
}
7274

73-
func (n *Node) Read() error {
74-
if err := n.readConfig(); err != nil {
75+
func (n *Node) Read(network *Network, dataDir string) error {
76+
n.network = network
77+
78+
if err := n.readConfig(dataDir); err != nil {
79+
return err
80+
}
81+
if err := n.EnsureNodeID(); err != nil {
7582
return err
7683
}
7784
return n.readState()

0 commit comments

Comments
 (0)