Skip to content

Commit ae36212

Browse files
authored
[tmpnet] Ensure GetNodeURIs returns locally-accessible URIs to ensure kube compatibility (#3973)
1 parent 409ad90 commit ae36212

File tree

6 files changed

+124
-35
lines changed

6 files changed

+124
-35
lines changed

tests/antithesis/config.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,9 @@ func configForNewNetwork(
102102
c := &Config{
103103
Duration: duration,
104104
}
105-
c.URIs = make(CSV, len(testEnv.URIs))
106-
for i, nodeURI := range testEnv.URIs {
105+
localURIs := testEnv.GetNodeURIs()
106+
c.URIs = make(CSV, len(localURIs))
107+
for i, nodeURI := range localURIs {
107108
c.URIs[i] = nodeURI.URI
108109
}
109110
network := testEnv.GetNetwork()

tests/e2e/p/validator_sets.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,9 @@ var _ = e2e.DescribePChain("[Validator Sets]", func() {
8181
require.NoError(err)
8282

8383
tc.By("checking that validator sets are equal across all heights for all nodes", func() {
84-
pvmClients := make([]platformvm.Client, len(env.URIs))
85-
for i, nodeURI := range env.URIs {
84+
localURIs := env.GetNodeURIs()
85+
pvmClients := make([]platformvm.Client, len(localURIs))
86+
for i, nodeURI := range localURIs {
8687
pvmClients[i] = platformvm.NewClient(nodeURI.URI)
8788
// Ensure that the height of the target node is at least the expected height
8889
tc.Eventually(

tests/e2e/x/transfer/virtuous.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,12 @@ var _ = e2e.DescribeXChainSerial("[Virtuous Transfer Tx AVAX]", func() {
4747

4848
ginkgo.It("can issue a virtuous transfer tx for AVAX asset",
4949
func() {
50-
env := e2e.GetEnv(tc)
51-
rpcEps := make([]string, len(env.URIs))
52-
for i, nodeURI := range env.URIs {
50+
var (
51+
env = e2e.GetEnv(tc)
52+
localURIs = env.GetNodeURIs()
53+
rpcEps = make([]string, len(localURIs))
54+
)
55+
for i, nodeURI := range localURIs {
5356
rpcEps[i] = nodeURI.URI
5457
}
5558

tests/fixture/e2e/env.go

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ type TestEnvironment struct {
4646
RootNetworkDir string
4747
// The directory where the test network configuration is stored
4848
NetworkDir string
49-
// URIs used to access the API endpoints of nodes of the network
50-
URIs []tmpnet.NodeURI
5149
// Pre-funded key for this ginkgo process
5250
PreFundedKey *secp256k1.PrivateKey
5351
// The duration to wait before shutting down private networks. A
@@ -66,7 +64,6 @@ func GetEnv(tc tests.TestContext) *TestEnvironment {
6664
return &TestEnvironment{
6765
RootNetworkDir: env.RootNetworkDir,
6866
NetworkDir: env.NetworkDir,
69-
URIs: env.URIs,
7067
PreFundedKey: env.PreFundedKey,
7168
PrivateNetworkShutdownDelay: env.PrivateNetworkShutdownDelay,
7269
testContext: tc,
@@ -210,30 +207,85 @@ func NewTestEnvironment(tc tests.TestContext, flagVars *FlagVars, desiredNetwork
210207
"not enough pre-funded keys for the requested number of parallel test processes",
211208
)
212209

213-
uris := network.GetNodeURIs()
214-
require.NotEmpty(uris, "network contains no nodes")
215-
tc.Log().Info("network nodes are available",
216-
zap.Any("uris", uris),
217-
)
218-
219-
return &TestEnvironment{
210+
env := &TestEnvironment{
220211
RootNetworkDir: flagVars.RootNetworkDir(),
221212
NetworkDir: network.Dir,
222-
URIs: uris,
223213
PrivateNetworkShutdownDelay: flagVars.NetworkShutdownDelay(),
224214
testContext: tc,
225215
}
216+
217+
if network.DefaultRuntimeConfig.Process != nil {
218+
// Display node IDs and URIs for process-based networks since the nodes are guaranteed to be network accessible
219+
uris := env.GetNodeURIs()
220+
require.NotEmpty(uris, "network contains no nodes")
221+
tc.Log().Info("network nodes are available",
222+
zap.Any("uris", uris),
223+
)
224+
} else {
225+
// Only display node IDs for kube-based networks since the nodes may not be network accessible and
226+
// port-forwarded URIs are ephemeral
227+
nodeIDs := network.GetAvailableNodeIDs()
228+
require.NotEmpty(nodeIDs, "network contains no nodes")
229+
tc.Log().Info("network nodes are available. Not showing node URIs since kube nodes may be running remotely.",
230+
zap.Strings("nodeIDs", nodeIDs),
231+
)
232+
}
233+
234+
return env
235+
}
236+
237+
// Retrieve URIs for validator nodes of the shared network. The URIs
238+
// are only guaranteed to be accessible until the environment test
239+
// context is torn down (usually the duration of execution of a single
240+
// test).
241+
func (te *TestEnvironment) GetNodeURIs() []tmpnet.NodeURI {
242+
var (
243+
tc = te.testContext
244+
network = te.GetNetwork()
245+
)
246+
uris, err := network.GetNodeURIs(tc.DefaultContext(), tc.DeferCleanup)
247+
require.NoError(tc, err)
248+
return uris
226249
}
227250

228-
// Retrieve a random URI to naively attempt to spread API load across
229-
// nodes.
251+
// Retrieve a random URI to naively attempt to spread API load across nodes.
230252
func (te *TestEnvironment) GetRandomNodeURI() tmpnet.NodeURI {
231-
r := rand.New(rand.NewSource(time.Now().Unix())) //#nosec G404
232-
nodeURI := te.URIs[r.Intn(len(te.URIs))]
233-
te.testContext.Log().Info("targeting random node",
253+
var (
254+
tc = te.testContext
255+
r = rand.New(rand.NewSource(time.Now().Unix())) //#nosec G404
256+
network = te.GetNetwork()
257+
availableNodes = []*tmpnet.Node{}
258+
)
259+
260+
for _, node := range network.Nodes {
261+
if node.IsEphemeral {
262+
// Avoid returning URIs for nodes whose lifespan is indeterminate
263+
continue
264+
}
265+
if !node.IsRunning() {
266+
// Only running nodes have URIs
267+
continue
268+
}
269+
availableNodes = append(availableNodes, node)
270+
}
271+
272+
require.NotEmpty(tc, availableNodes, "no available nodes to target")
273+
274+
// Use a local URI for the node to ensure compatibility with kube
275+
randomNode := availableNodes[r.Intn(len(availableNodes))]
276+
uri, cancel, err := randomNode.GetLocalURI(tc.DefaultContext())
277+
require.NoError(tc, err)
278+
tc.DeferCleanup(cancel)
279+
280+
nodeURI := tmpnet.NodeURI{
281+
NodeID: randomNode.NodeID,
282+
URI: uri,
283+
}
284+
tc.Log().Info("targeting random node",
234285
zap.Stringer("nodeID", nodeURI.NodeID),
235286
zap.String("uri", nodeURI.URI),
236287
)
288+
237289
return nodeURI
238290
}
239291

tests/fixture/tmpnet/network.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -767,8 +767,21 @@ func (n *Network) GetNode(nodeID ids.NodeID) (*Node, error) {
767767
return nil, fmt.Errorf("%s is not known to the network", nodeID)
768768
}
769769

770-
func (n *Network) GetNodeURIs() []NodeURI {
771-
return GetNodeURIs(n.Nodes)
770+
// GetNodeURIs returns the URIs of nodes in the network that are running and not ephemeral. The URIs
771+
// returned are guaranteed be reachable by the caller until the cleanup function is called regardless
772+
// of whether the nodes are running as local processes or in a kube cluster.
773+
func (n *Network) GetNodeURIs(ctx context.Context, deferCleanupFunc func(func())) ([]NodeURI, error) {
774+
return GetNodeURIs(ctx, n.Nodes, deferCleanupFunc)
775+
}
776+
777+
// GetAvailableNodeIDs returns the node IDs of nodes in the network that are running and not ephemeral.
778+
func (n *Network) GetAvailableNodeIDs() []string {
779+
availableNodes := FilterAvailableNodes(n.Nodes)
780+
ids := make([]string, len(availableNodes))
781+
for _, node := range availableNodes {
782+
ids = append(ids, node.NodeID.String())
783+
}
784+
return ids
772785
}
773786

774787
// Retrieves bootstrap IPs and IDs for all non-ephemeral nodes except the skipped one

tests/fixture/tmpnet/utils.go

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,42 @@ type NodeURI struct {
5353
URI string
5454
}
5555

56-
func GetNodeURIs(nodes []*Node) []NodeURI {
57-
uris := make([]NodeURI, 0, len(nodes))
56+
// GetNodeURIs returns the URIs of the provided nodes that are running and not ephemeral. The URIs returned
57+
// are guaranteed be reachable by the caller until the cleanup function is called regardless of whether the
58+
// nodes are running as local processes or in a kube cluster.
59+
func GetNodeURIs(ctx context.Context, nodes []*Node, deferCleanupFunc func(func())) ([]NodeURI, error) {
60+
availableNodes := FilterAvailableNodes(nodes)
61+
uris := make([]NodeURI, 0, len(availableNodes))
62+
for _, node := range availableNodes {
63+
uri, cancel, err := node.GetLocalURI(ctx)
64+
if err != nil {
65+
return nil, err
66+
}
67+
deferCleanupFunc(cancel)
68+
uris = append(uris, NodeURI{
69+
NodeID: node.NodeID,
70+
URI: uri,
71+
})
72+
}
73+
74+
return uris, nil
75+
}
76+
77+
// FilteredAvailableNodes filters the provided nodes by whether they are running and not ephemeral.
78+
func FilterAvailableNodes(nodes []*Node) []*Node {
79+
filteredNodes := make([]*Node, 0, len(nodes))
5880
for _, node := range nodes {
5981
if node.IsEphemeral {
6082
// Avoid returning URIs for nodes whose lifespan is indeterminate
6183
continue
6284
}
63-
// Only append URIs that are not empty. A node may have an
64-
// empty URI if it is not currently running.
65-
if node.IsRunning() {
66-
uris = append(uris, NodeURI{
67-
NodeID: node.NodeID,
68-
URI: node.URI,
69-
})
85+
if !node.IsRunning() {
86+
// Only running nodes have URIs
87+
continue
7088
}
89+
filteredNodes = append(filteredNodes, node)
7190
}
72-
return uris
91+
return filteredNodes
7392
}
7493

7594
// Marshal to json with default prefix and indent.

0 commit comments

Comments
 (0)