Skip to content

Commit ca83ff8

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

File tree

11 files changed

+104
-146
lines changed

11 files changed

+104
-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

+10-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)

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
@@ -240,13 +240,6 @@ func (n *Network) EnsureDefaultConfig(log logging.Logger) error {
240240
n.PrimaryChainConfigs[alias].SetDefaults(chainConfig)
241241
}
242242

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

@@ -504,23 +497,22 @@ func (n *Network) RestartNode(ctx context.Context, log logging.Logger, node *Nod
504497

505498
// Stops all nodes in the network.
506499
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 {
500+
// Ensure the node state is up-to-date
501+
if err := n.readNodes(); err != nil {
510502
return err
511503
}
512504

513505
var errs []error
514506

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

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

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

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-
}
548+
// Ensure a data directory if not already set
549+
if len(node.DataDir) == 0 {
550+
node.DataDir = filepath.Join(n.Dir, node.NodeID.String())
565551
}
566552

567553
return nil
@@ -768,16 +754,13 @@ func (n *Network) GetNodeURIs() []NodeURI {
768754
// collecting the bootstrap details for restarting a node).
769755
// For consumption outside of avalanchego. Needs to be kept exported.
770756
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 {
757+
bootstrapIPs := []string{}
758+
bootstrapIDs := []string{}
759+
for _, node := range n.Nodes {
760+
if node.IsEphemeral {
761+
// Ephemeral nodes are not guaranteed to stay running
762+
continue
763+
}
781764
if skippedNode != nil && node.NodeID == skippedNode.NodeID {
782765
continue
783766
}
@@ -940,12 +923,16 @@ func (n *Network) writeNodeFlags(log logging.Logger, node *Node) error {
940923
// Only configure the plugin dir with a non-empty value to ensure the use of
941924
// the default value (`[datadir]/plugins`) when no plugin dir is configured.
942925
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)
926+
if processConfig != nil {
927+
if len(processConfig.PluginDir) > 0 {
928+
// Ensure the plugin directory exists or the node will fail to start
929+
if err := os.MkdirAll(processConfig.PluginDir, perms.ReadWriteExecute); err != nil {
930+
return fmt.Errorf("failed to create plugin dir: %w", err)
931+
}
932+
flags.SetDefault(config.PluginDirKey, processConfig.PluginDir)
947933
}
948-
flags.SetDefault(config.PluginDirKey, processConfig.PluginDir)
934+
935+
flags.SetDefault(config.DataDirKey, node.DataDir)
949936
}
950937

951938
// 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
@@ -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

@@ -129,13 +151,13 @@ func (n *Network) readConfig() error {
129151

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

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

0 commit comments

Comments
 (0)