Skip to content

Commit fa21d78

Browse files
authored
tmpnet: Separate node into orchestration, config and process (#2460)
1 parent 618f02c commit fa21d78

15 files changed

+554
-357
lines changed

tests/e2e/faultinjection/duplicate_node_id.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ var _ = ginkgo.Describe("Duplicate node handling", func() {
4949
require.ErrorIs(err, context.DeadlineExceeded)
5050

5151
ginkgo.By("stopping the first new node")
52-
require.NoError(node1.Stop())
52+
require.NoError(node1.Stop(e2e.DefaultContext()))
5353

5454
ginkgo.By("checking that the second new node becomes healthy within timeout")
5555
e2e.WaitForHealthy(node2)

tests/e2e/p/interchain_workflow.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainL
209209
require.Positive(balance.Cmp(big.NewInt(0)))
210210

211211
ginkgo.By("stopping validator node to free up resources for a bootstrap check")
212-
require.NoError(node.Stop())
212+
require.NoError(node.Stop(e2e.DefaultContext()))
213213

214214
e2e.CheckBootstrapIsPossible(network)
215215
})

tests/e2e/p/staking_rewards.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() {
227227
})
228228

229229
ginkgo.By("stopping beta node to prevent it and its delegator from receiving a validation reward")
230-
require.NoError(betaNode.Stop())
230+
require.NoError(betaNode.Stop(e2e.DefaultContext()))
231231

232232
ginkgo.By("retrieving staking periods from the chain")
233233
data, err := pvmClient.GetCurrentValidators(e2e.DefaultContext(), constants.PlatformChainID, []ids.NodeID{alphaNodeID})
@@ -302,7 +302,7 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() {
302302
}
303303

304304
ginkgo.By("stopping alpha to free up resources for a bootstrap check")
305-
require.NoError(alphaNode.Stop())
305+
require.NoError(alphaNode.Stop(e2e.DefaultContext()))
306306

307307
e2e.CheckBootstrapIsPossible(network)
308308
})

tests/fixture/e2e/env.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,5 @@ func (te *TestEnvironment) NewPrivateNetwork() *tmpnet.Network {
132132
privateNetworksDir := filepath.Join(sharedNetwork.Dir, PrivateNetworksDirName)
133133
te.require.NoError(os.MkdirAll(privateNetworksDir, perms.ReadWriteExecute))
134134

135-
return StartNetwork(sharedNetwork.ExecPath, privateNetworksDir)
135+
return StartNetwork(sharedNetwork.AvalancheGoPath, privateNetworksDir)
136136
}

tests/fixture/e2e/helpers.go

+13-25
Original file line numberDiff line numberDiff line change
@@ -118,22 +118,21 @@ func Eventually(condition func() bool, waitFor time.Duration, tick time.Duration
118118
}
119119
}
120120

121-
// Add an ephemeral node that is only intended to be used by a single test. Its ID and
122-
// URI are not intended to be returned from the Network instance to minimize
123-
// accessibility from other tests.
121+
// Adds an ephemeral node intended to be used by a single test.
124122
func AddEphemeralNode(network *tmpnet.Network, flags tmpnet.FlagsMap) *tmpnet.Node {
125123
require := require.New(ginkgo.GinkgoT())
126124

127-
node, err := network.AddEphemeralNode(ginkgo.GinkgoWriter, flags)
125+
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
126+
defer cancel()
127+
node, err := network.AddEphemeralNode(ctx, ginkgo.GinkgoWriter, flags)
128128
require.NoError(err)
129129

130-
// Ensure node is stopped on teardown. It's configuration is not removed to enable
131-
// collection in CI to aid in troubleshooting failures.
132130
ginkgo.DeferCleanup(func() {
133-
tests.Outf("Shutting down ephemeral node %s\n", node.NodeID)
134-
require.NoError(node.Stop())
131+
tests.Outf("shutting down ephemeral node %q\n", node.NodeID)
132+
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
133+
defer cancel()
134+
require.NoError(node.Stop(ctx))
135135
})
136-
137136
return node
138137
}
139138

@@ -191,26 +190,13 @@ func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option {
191190

192191
// Verify that a new node can bootstrap into the network.
193192
func CheckBootstrapIsPossible(network *tmpnet.Network) {
194-
require := require.New(ginkgo.GinkgoT())
195-
196193
if len(os.Getenv(SkipBootstrapChecksEnvName)) > 0 {
197194
tests.Outf("{{yellow}}Skipping bootstrap check due to the %s env var being set", SkipBootstrapChecksEnvName)
198195
return
199196
}
200197
ginkgo.By("checking if bootstrap is possible with the current network state")
201198

202-
// Call network.AddEphemeralNode instead of AddEphemeralNode to support
203-
// checking for bootstrap implicitly on teardown via a function registered
204-
// with ginkgo.DeferCleanup. It's not possible to call DeferCleanup from
205-
// within a function called by DeferCleanup.
206-
node, err := network.AddEphemeralNode(ginkgo.GinkgoWriter, tmpnet.FlagsMap{})
207-
require.NoError(err)
208-
209-
defer func() {
210-
tests.Outf("Shutting down ephemeral node %s\n", node.NodeID)
211-
require.NoError(node.Stop())
212-
}()
213-
199+
node := AddEphemeralNode(network, tmpnet.FlagsMap{})
214200
WaitForHealthy(node)
215201
}
216202

@@ -224,7 +210,7 @@ func StartNetwork(avalancheGoExecPath string, networkDir string) *tmpnet.Network
224210
networkDir,
225211
&tmpnet.Network{
226212
NodeRuntimeConfig: tmpnet.NodeRuntimeConfig{
227-
ExecPath: avalancheGoExecPath,
213+
AvalancheGoPath: avalancheGoExecPath,
228214
},
229215
},
230216
tmpnet.DefaultNodeCount,
@@ -233,7 +219,9 @@ func StartNetwork(avalancheGoExecPath string, networkDir string) *tmpnet.Network
233219
require.NoError(err)
234220
ginkgo.DeferCleanup(func() {
235221
tests.Outf("Shutting down network\n")
236-
require.NoError(network.Stop())
222+
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
223+
defer cancel()
224+
require.NoError(network.Stop(ctx))
237225
})
238226

239227
tests.Outf("{{green}}Successfully started network{{/}}\n")

tests/fixture/tmpnet/README.md

+24-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# tmpnet (temporary network fixture)
1+
# tmpnet - temporary network orchestration
22

33
This package implements a simple orchestrator for the avalanchego
44
nodes of a temporary network. Configuration is stored on disk, and
@@ -31,6 +31,8 @@ the following non-test files:
3131
| genesis.go | | Creates test genesis |
3232
| network.go | Network | Orchestrates and configures temporary networks |
3333
| node.go | Node | Orchestrates and configures nodes |
34+
| node_config.go | Node | Reads and writes node configuration |
35+
| node_process.go | NodeProcess | Orchestrates node processes |
3436
| utils.go | | Defines shared utility functions |
3537

3638
## Usage
@@ -76,7 +78,7 @@ network, _ := tmpnet.StartNetwork(
7678
ginkgo.GinkgoWriter, // Writer to report progress of network start
7779
"", // Use default root dir (~/.tmpnet)
7880
&tmpnet.Network{
79-
DefaultRuntime: tmpnet.NodeRuntimeConfig{
81+
NodeRuntimeConfig: tmpnet.NodeRuntimeConfig{
8082
ExecPath: "/path/to/avalanchego", // Defining the avalanchego exec path is required
8183
},
8284
},
@@ -102,7 +104,7 @@ network, _ := tmpnet.StartNetwork(
102104
ginkgo.GinkgoWriter,
103105
"",
104106
&tmpnet.Network{
105-
DefaultRuntime: tmpnet.NodeRuntimeConfig{
107+
NodeRuntimeConfig: tmpnet.NodeRuntimeConfig{
106108
ExecPath: "/path/to/avalanchego",
107109
},
108110
Nodes: []*Node{
@@ -147,9 +149,10 @@ HOME
147149
├── NodeID-37E8UK3x2YFsHE3RdALmfWcppcZ1eTuj9 // The ID of a node is the name of its data dir
148150
│ ├── chainData
149151
│ │ └── ...
150-
│ ├── config.json // Node flags
152+
│ ├── config.json // Node runtime configuration
151153
│ ├── db
152154
│ │ └── ...
155+
│ ├── flags.json // Node flags
153156
│ ├── logs
154157
│ │ └── ...
155158
│ ├── plugins
@@ -160,11 +163,7 @@ HOME
160163
│ └── config.json // C-Chain config for all nodes
161164
├── defaults.json // Default flags and configuration for network
162165
├── genesis.json // Genesis for all nodes
163-
├── network.env // Sets network dir env to simplify use of network
164-
└── ephemeral // Parent directory for ephemeral nodes (e.g. created by tests)
165-
└─ NodeID-FdxnAvr4jK9XXAwsYZPgWAHW2QnwSZ // Data dir for an ephemeral node
166-
└── ...
167-
166+
└── network.env // Sets network dir env var to simplify network usage
168167
```
169168

170169
### Default flags and configuration
@@ -203,19 +202,33 @@ this file (i.e. `source network.env`) in a shell will configure ginkgo
203202
e2e and the `tmpnetctl` cli to target the network path specified in
204203
the env var.
205204

205+
Set `TMPNET_ROOT_DIR` to specify the root directory in which to create
206+
the configuration directory of new networks
207+
(e.g. `$TMPNET_ROOT_DIR/[network-dir]`). The default root directory is
208+
`~/.tmpdir/networks`. Configuring the root directory is only relevant
209+
when creating new networks as the path of existing networks will
210+
already have been set.
211+
206212
### Node configuration
207213

208214
The data dir for a node is set by default to
209215
`[network-path]/[node-id]`. A node can be configured to use a
210216
non-default path by explicitly setting the `--data-dir`
211217
flag.
212218

219+
#### Runtime config
220+
221+
The details required to configure a node's execution are written to
222+
`[network-path]/[node-id]/config.json`. This file contains the
223+
runtime-specific details like the path of the avalanchego binary to
224+
start the node with.
225+
213226
#### Flags
214227

215228
All flags used to configure a node are written to
216-
`[network-path]/[node-id]/config.json` so that a node can be
229+
`[network-path]/[node-id]/flags.json` so that a node can be
217230
configured with only a single argument:
218-
`--config-file=/path/to/config.json`. This simplifies node launch and
231+
`--config-file=/path/to/flags.json`. This simplifies node launch and
219232
ensures all parameters used to launch a node can be modified by
220233
editing the config file.
221234

tests/fixture/tmpnet/cmd/main.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ func main() {
6262

6363
network := &tmpnet.Network{
6464
NodeRuntimeConfig: tmpnet.NodeRuntimeConfig{
65-
ExecPath: execPath,
65+
AvalancheGoPath: execPath,
6666
},
6767
}
68-
ctx, cancel := context.WithTimeout(context.Background(), tmpnet.DefaultNetworkStartTimeout)
68+
ctx, cancel := context.WithTimeout(context.Background(), tmpnet.DefaultNetworkTimeout)
6969
defer cancel()
7070
network, err := tmpnet.StartNetwork(ctx, os.Stdout, rootDir, network, int(nodeCount), int(preFundedKeyCount))
7171
if err != nil {
@@ -105,7 +105,9 @@ func main() {
105105
if len(networkDir) == 0 {
106106
return errNetworkDirRequired
107107
}
108-
if err := tmpnet.StopNetwork(networkDir); err != nil {
108+
ctx, cancel := context.WithTimeout(context.Background(), tmpnet.DefaultNetworkTimeout)
109+
defer cancel()
110+
if err := tmpnet.StopNetwork(ctx, networkDir); err != nil {
109111
return err
110112
}
111113
fmt.Fprintf(os.Stdout, "Stopped network configured at: %s\n", networkDir)

tests/fixture/tmpnet/defaults.go

+5-6
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,10 @@ import (
1212
const (
1313
// Constants defining the names of shell variables whose value can
1414
// configure temporary network orchestration.
15-
AvalancheGoPathEnvName = "AVALANCHEGO_PATH"
16-
NetworkDirEnvName = "TMPNET_NETWORK_DIR"
17-
RootDirEnvName = "TMPNET_ROOT_DIR"
15+
NetworkDirEnvName = "TMPNET_NETWORK_DIR"
16+
RootDirEnvName = "TMPNET_ROOT_DIR"
1817

19-
DefaultNetworkStartTimeout = 2 * time.Minute
20-
DefaultNodeInitTimeout = 10 * time.Second
21-
DefaultNodeStopTimeout = 5 * time.Second
18+
DefaultNetworkTimeout = 2 * time.Minute
2219

2320
// Minimum required to ensure connectivity-based health checks will pass
2421
DefaultNodeCount = 2
@@ -28,6 +25,8 @@ const (
2825

2926
// A short minimum stake duration enables testing of staking logic.
3027
DefaultMinStakeDuration = time.Second
28+
29+
defaultConfigFilename = "config.json"
3130
)
3231

3332
// A set of flags appropriate for testing.

0 commit comments

Comments
 (0)