Skip to content

Commit 3b43707

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

File tree

11 files changed

+109
-146
lines changed

11 files changed

+109
-146
lines changed

tests/antithesis/init_db.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func initBootstrapDB(network *tmpnet.Network, destPath string) error {
4545
}
4646

4747
// Copy the db state from the bootstrap node to the compose volume path.
48-
sourcePath := filepath.Join(network.Nodes[0].GetDataDir(), "db")
48+
sourcePath := filepath.Join(network.Nodes[0].DataDir, "db")
4949
if err := os.MkdirAll(destPath, perms.ReadWriteExecute); err != nil {
5050
return fmt.Errorf("failed to create db path %q: %w", destPath, err)
5151
}

tests/e2e/faultinjection/duplicate_node_id.go

+15-12
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package faultinjection
55

66
import (
77
"context"
8-
"fmt"
98

109
"github.com/onsi/ginkgo/v2"
1110
"github.com/stretchr/testify/require"
@@ -27,23 +26,22 @@ var _ = ginkgo.Describe("Duplicate node handling", func() {
2726
network := e2e.GetEnv(tc).GetNetwork()
2827

2928
tc.By("creating new node")
30-
node1 := e2e.AddEphemeralNode(tc, network, tmpnet.FlagsMap{})
29+
node1 := e2e.AddEphemeralNode(tc, network, tmpnet.NewEphemeralNode(tmpnet.FlagsMap{}))
3130
e2e.WaitForHealthy(tc, node1)
3231

3332
tc.By("checking that the new node is connected to its peers")
3433
checkConnectedPeers(tc, network.Nodes, node1)
3534

3635
tc.By("creating a second new node with the same staking keypair as the first new node")
37-
node1Flags := node1.Flags
38-
node2Flags := tmpnet.FlagsMap{
39-
config.StakingTLSKeyContentKey: node1Flags[config.StakingTLSKeyContentKey],
40-
config.StakingCertContentKey: node1Flags[config.StakingCertContentKey],
41-
// Construct a unique data dir to ensure the two nodes' data will be stored
42-
// separately. Usually the dir name is the node ID but in this one case the nodes have
43-
// the same node ID.
44-
config.DataDirKey: fmt.Sprintf("%s-second", node1Flags[config.DataDirKey]),
45-
}
46-
node2 := e2e.AddEphemeralNode(tc, network, node2Flags)
36+
node2 := tmpnet.NewEphemeralNode(tmpnet.FlagsMap{
37+
config.StakingTLSKeyContentKey: node1.Flags[config.StakingTLSKeyContentKey],
38+
config.StakingCertContentKey: node1.Flags[config.StakingCertContentKey],
39+
})
40+
// Construct a unique data dir to ensure the two nodes' data will be stored
41+
// separately. Usually the dir name is the node ID but in this one case the nodes have
42+
// the same node ID.
43+
node2.DataDir = node1.DataDir + "-second"
44+
_ = e2e.AddEphemeralNode(tc, network, node2)
4745

4846
tc.By("checking that the second new node fails to become healthy before timeout")
4947
err := tmpnet.WaitForHealthy(tc.DefaultContext(), node2)
@@ -77,6 +75,11 @@ func checkConnectedPeers(tc tests.TestContext, existingNodes []*tmpnet.Node, new
7775
}
7876

7977
for _, existingNode := range existingNodes {
78+
if existingNode.IsEphemeral {
79+
// Ephemeral nodes may not be running
80+
continue
81+
}
82+
8083
// Check that the existing node is a peer of the new node
8184
require.True(peerIDs.Contains(existingNode.NodeID))
8285

tests/e2e/p/interchain_workflow.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainL
108108
})
109109

110110
tc.By("adding new node and waiting for it to report healthy")
111-
node := e2e.AddEphemeralNode(tc, network, tmpnet.FlagsMap{})
111+
node := e2e.AddEphemeralNode(tc, network, tmpnet.NewEphemeralNode(tmpnet.FlagsMap{}))
112112
e2e.WaitForHealthy(tc, node)
113113

114114
tc.By("retrieving new node's id and pop")

tests/e2e/p/l1.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,9 @@ var _ = e2e.DescribePChain("[L1]", func() {
172172
})
173173

174174
tc.By("creating the genesis validator")
175-
subnetGenesisNode := e2e.AddEphemeralNode(tc, env.GetNetwork(), tmpnet.FlagsMap{
175+
subnetGenesisNode := e2e.AddEphemeralNode(tc, env.GetNetwork(), tmpnet.NewEphemeralNode(tmpnet.FlagsMap{
176176
config.TrackSubnetsKey: subnetID.String(),
177-
})
177+
}))
178178

179179
genesisNodePoP, err := subnetGenesisNode.GetProofOfPossession()
180180
require.NoError(err)
@@ -348,9 +348,9 @@ var _ = e2e.DescribePChain("[L1]", func() {
348348
tc.By("advancing the proposervm P-chain height", advanceProposerVMPChainHeight)
349349

350350
tc.By("creating the validator to register")
351-
subnetRegisterNode := e2e.AddEphemeralNode(tc, env.GetNetwork(), tmpnet.FlagsMap{
351+
subnetRegisterNode := e2e.AddEphemeralNode(tc, env.GetNetwork(), tmpnet.NewEphemeralNode(tmpnet.FlagsMap{
352352
config.TrackSubnetsKey: subnetID.String(),
353-
})
353+
}))
354354

355355
registerNodePoP, err := subnetRegisterNode.GetProofOfPossession()
356356
require.NoError(err)

tests/e2e/p/staking_rewards.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() {
5555
})
5656

5757
tc.By("adding alpha node, whose uptime should result in a staking reward")
58-
alphaNode := e2e.AddEphemeralNode(tc, network, tmpnet.FlagsMap{})
58+
alphaNode := e2e.AddEphemeralNode(tc, network, tmpnet.NewEphemeralNode(tmpnet.FlagsMap{}))
5959
tc.By("adding beta node, whose uptime should not result in a staking reward")
60-
betaNode := e2e.AddEphemeralNode(tc, network, tmpnet.FlagsMap{})
60+
betaNode := e2e.AddEphemeralNode(tc, network, tmpnet.NewEphemeralNode(tmpnet.FlagsMap{}))
6161

6262
// Wait to check health until both nodes have started to minimize the duration
6363
// required for both nodes to report healthy.

tests/fixture/e2e/helpers.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,9 @@ func NewEthClient(tc tests.TestContext, nodeURI tmpnet.NodeURI) ethclient.Client
133133
}
134134

135135
// Adds an ephemeral node intended to be used by a single test.
136-
func AddEphemeralNode(tc tests.TestContext, network *tmpnet.Network, flags tmpnet.FlagsMap) *tmpnet.Node {
136+
func AddEphemeralNode(tc tests.TestContext, network *tmpnet.Network, node *tmpnet.Node) *tmpnet.Node {
137137
require := require.New(tc)
138138

139-
node := tmpnet.NewEphemeralNode(flags)
140139
require.NoError(network.StartNode(tc.DefaultContext(), tc.Log(), node))
141140

142141
tc.DeferCleanup(func() {

tests/fixture/tmpnet/network.go

+24-37
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,6 @@ func (n *Network) EnsureDefaultConfig(log logging.Logger) error {
239239
n.PrimaryChainConfigs[alias].SetDefaults(chainConfig)
240240
}
241241

242-
// Ensure nodes are configured
243-
for i := range n.Nodes {
244-
if err := n.EnsureNodeConfig(n.Nodes[i]); err != nil {
245-
return err
246-
}
247-
}
248-
249242
return nil
250243
}
251244

@@ -503,23 +496,22 @@ func (n *Network) RestartNode(ctx context.Context, log logging.Logger, node *Nod
503496

504497
// Stops all nodes in the network.
505498
func (n *Network) Stop(ctx context.Context) error {
506-
// Target all nodes, including the ephemeral ones
507-
nodes, err := ReadNodes(n, true /* includeEphemeral */)
508-
if err != nil {
499+
// Ensure the node state is up-to-date
500+
if err := n.readNodes(); err != nil {
509501
return err
510502
}
511503

512504
var errs []error
513505

514506
// Initiate stop on all nodes
515-
for _, node := range nodes {
507+
for _, node := range n.Nodes {
516508
if err := node.InitiateStop(ctx); err != nil {
517509
errs = append(errs, fmt.Errorf("failed to stop node %s: %w", node.NodeID, err))
518510
}
519511
}
520512

521513
// Wait for stop to complete on all nodes
522-
for _, node := range nodes {
514+
for _, node := range n.Nodes {
523515
if err := node.WaitForStopped(ctx); err != nil {
524516
errs = append(errs, fmt.Errorf("failed to wait for node %s to stop: %w", node.NodeID, err))
525517
}
@@ -543,8 +535,7 @@ func (n *Network) Restart(ctx context.Context, log logging.Logger) error {
543535
}
544536

545537
// Ensures the provided node has the configuration it needs to start. If the data dir is not
546-
// set, it will be defaulted to [nodeParentDir]/[node ID]. For a not-yet-created network,
547-
// no action will be taken.
538+
// set, it will be defaulted to [nodeParentDir]/[node ID].
548539
func (n *Network) EnsureNodeConfig(node *Node) error {
549540
// Ensure the node has access to network configuration
550541
node.network = n
@@ -553,14 +544,9 @@ func (n *Network) EnsureNodeConfig(node *Node) error {
553544
return err
554545
}
555546

556-
if len(n.Dir) > 0 {
557-
// Ensure the node's data dir is configured
558-
dataDir := node.GetDataDir()
559-
if len(dataDir) == 0 {
560-
// NodeID will have been set by EnsureKeys
561-
dataDir = filepath.Join(n.Dir, node.NodeID.String())
562-
node.Flags[config.DataDirKey] = dataDir
563-
}
547+
// Ensure a data directory if not already set
548+
if len(node.DataDir) == 0 {
549+
node.DataDir = filepath.Join(n.Dir, node.NodeID.String())
564550
}
565551

566552
return nil
@@ -767,16 +753,13 @@ func (n *Network) GetNodeURIs() []NodeURI {
767753
// collecting the bootstrap details for restarting a node).
768754
// For consumption outside of avalanchego. Needs to be kept exported.
769755
func (n *Network) GetBootstrapIPsAndIDs(skippedNode *Node) ([]string, []string, error) {
770-
// Collect staking addresses of non-ephemeral nodes for use in bootstrapping a node
771-
nodes, err := ReadNodes(n, false /* includeEphemeral */)
772-
if err != nil {
773-
return nil, nil, fmt.Errorf("failed to read network's nodes: %w", err)
774-
}
775-
var (
776-
bootstrapIPs = make([]string, 0, len(nodes))
777-
bootstrapIDs = make([]string, 0, len(nodes))
778-
)
779-
for _, node := range nodes {
756+
bootstrapIPs := []string{}
757+
bootstrapIDs := []string{}
758+
for _, node := range n.Nodes {
759+
if node.IsEphemeral {
760+
// Ephemeral nodes are not guaranteed to stay running
761+
continue
762+
}
780763
if skippedNode != nil && node.NodeID == skippedNode.NodeID {
781764
continue
782765
}
@@ -934,12 +917,16 @@ func (n *Network) writeNodeFlags(log logging.Logger, node *Node) error {
934917
// Only configure the plugin dir with a non-empty value to ensure the use of
935918
// the default value (`[datadir]/plugins`) when no plugin dir is configured.
936919
processConfig := node.getRuntimeConfig().Process
937-
if processConfig != nil && len(processConfig.PluginDir) > 0 {
938-
// Ensure the plugin directory exists or the node will fail to start
939-
if err := os.MkdirAll(processConfig.PluginDir, perms.ReadWriteExecute); err != nil {
940-
return fmt.Errorf("failed to create plugin dir: %w", err)
920+
if processConfig != nil {
921+
if len(processConfig.PluginDir) > 0 {
922+
// Ensure the plugin directory exists or the node will fail to start
923+
if err := os.MkdirAll(processConfig.PluginDir, perms.ReadWriteExecute); err != nil {
924+
return fmt.Errorf("failed to create plugin dir: %w", err)
925+
}
926+
flags.SetDefault(config.PluginDirKey, processConfig.PluginDir)
941927
}
942-
flags.SetDefault(config.PluginDirKey, processConfig.PluginDir)
928+
929+
flags.SetDefault(config.DataDirKey, node.DataDir)
943930
}
944931

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

tests/fixture/tmpnet/network_config.go

+32-10
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,35 @@ func (n *Network) readNetwork() error {
5656
return n.readConfig()
5757
}
5858

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

@@ -128,13 +150,13 @@ func (n *Network) readConfig() error {
128150

129151
// The subset of network fields to store in the network config file.
130152
type serializedNetworkConfig struct {
131-
UUID string `json:",omitempty"`
132-
Owner string `json:",omitempty"`
133-
PrimarySubnetConfig FlagsMap `json:",omitempty"`
134-
PrimaryChainConfigs map[string]FlagsMap `json:",omitempty"`
135-
DefaultFlags FlagsMap `json:",omitempty"`
136-
DefaultRuntimeConfig NodeRuntimeConfig `json:",omitempty"`
137-
PreFundedKeys []*secp256k1.PrivateKey `json:",omitempty"`
153+
UUID string `json:"uuid,omitempty"`
154+
Owner string `json:"owner,omitempty"`
155+
PrimarySubnetConfig FlagsMap `json:"primarySubnetConfig,omitempty"`
156+
PrimaryChainConfigs map[string]FlagsMap `json:"primaryChainConfigs,omitempty"`
157+
DefaultFlags FlagsMap `json:"defaultFlags,omitempty"`
158+
DefaultRuntimeConfig NodeRuntimeConfig `json:"defaultRuntimeConfig,omitempty"`
159+
PreFundedKeys []*secp256k1.PrivateKey `json:"preFundedKeys,omitempty"`
138160
}
139161

140162
func (n *Network) writeNetworkConfig() error {

0 commit comments

Comments
 (0)