From aa1d137f9bd6d0f8f30bb1dfbd4dca0906ff601a Mon Sep 17 00:00:00 2001 From: Tomas Srnka Date: Sun, 26 Jul 2026 22:18:36 +0200 Subject: [PATCH] test(api): ephemeral port for the fake orchestrator gRPC server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TestGetOrConnectNode_CacheMiss_DiscoversAndConnects bound a fixed port (consts.OrchestratorAPIPort, 5008) and flaked with 'address already in use' on shared CI runners and dev boxes running a real orchestrator. The helper now binds an ephemeral port and returns it; the mocked service registration carries that port so nomad discovery still dials the right listener. Pre-existing flake, independent of the multi-distro work — split out of #3381. Co-Authored-By: Claude Opus 4.8 --- .../api/internal/orchestrator/client_test.go | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/packages/api/internal/orchestrator/client_test.go b/packages/api/internal/orchestrator/client_test.go index c4b87ed504..aea3a5acfb 100644 --- a/packages/api/internal/orchestrator/client_test.go +++ b/packages/api/internal/orchestrator/client_test.go @@ -78,17 +78,12 @@ func (s *fakeInfoServer) ServiceInfo(context.Context, *emptypb.Empty) (*infogrpc }, nil } -// startFakeOrchestratorGRPC starts a gRPC server that responds to ServiceInfo -// requests. When addr is empty it listens on an ephemeral port; otherwise it -// binds to the given address (e.g. "127.0.0.1:5008"). -func startFakeOrchestratorGRPC(t *testing.T, nodeID string, addr string) { +// startFakeOrchestratorGRPC starts a fake ServiceInfo server on an ephemeral +// port and returns it; a fixed port flakes on shared runners. +func startFakeOrchestratorGRPC(t *testing.T, nodeID string) int { t.Helper() - if addr == "" { - addr = "127.0.0.1:0" - } - - lis, err := (&net.ListenConfig{}).Listen(t.Context(), "tcp", addr) + lis, err := (&net.ListenConfig{}).Listen(t.Context(), "tcp", "127.0.0.1:0") require.NoError(t, err) srv := grpc.NewServer(grpc.Creds(insecure.NewCredentials())) @@ -96,6 +91,8 @@ func startFakeOrchestratorGRPC(t *testing.T, nodeID string, addr string) { go srv.Serve(lis) t.Cleanup(srv.GracefulStop) + + return lis.Addr().(*net.TCPAddr).Port } // TestGetOrConnectNode_CacheHit verifies that when a node is already in the @@ -268,21 +265,16 @@ func TestConnectToNode_SingleflightDedup(t *testing.T) { // 3. This API instance has NOT yet synced (node is absent from o.nodes). // 4. A handler calls getOrConnectNode for a sandbox on that node. // -// The fake gRPC server listens on consts.OrchestratorAPIPort, matching the -// port carried by the mocked service registration. +// The fake gRPC server and the mocked service registration share an ephemeral +// port, so nomad discovery dials the right listener. func TestGetOrConnectNode_CacheMiss_DiscoversAndConnects(t *testing.T) { t.Parallel() orchestratorNodeID := "orch-node-42" nomadFullID := "aabbccdd11223344aabbccdd11223344aabbccdd" - // 1. Start a fake gRPC server on consts.OrchestratorAPIPort so that the - // address built by listNomadNodes matches our listener. - listenAddr := fmt.Sprintf("127.0.0.1:%d", consts.OrchestratorAPIPort) - startFakeOrchestratorGRPC(t, orchestratorNodeID, listenAddr) + port := startFakeOrchestratorGRPC(t, orchestratorNodeID) - // 2. Mock Nomad HTTP API returning a single service registration at - // 127.0.0.1. nomadClient := newNomadMock(t, func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/v1/service/orchestrator" { resp := []*nomadapi.ServiceRegistration{ @@ -291,7 +283,7 @@ func TestGetOrConnectNode_CacheMiss_DiscoversAndConnects(t *testing.T) { ServiceName: "orchestrator", NodeID: nomadFullID, Address: "127.0.0.1", - Port: int(consts.OrchestratorAPIPort), + Port: port, }, } w.Header().Set("Content-Type", "application/json")