Skip to content

Commit a9c0c01

Browse files
authored
chore: fix flake in listening ports test (#10833)
1 parent f20cc66 commit a9c0c01

File tree

4 files changed

+41
-16
lines changed

4 files changed

+41
-16
lines changed

agent/agent.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ type Options struct {
6868
EnvironmentVariables map[string]string
6969
Logger slog.Logger
7070
IgnorePorts map[int]string
71+
PortCacheDuration time.Duration
7172
SSHMaxTimeout time.Duration
7273
TailnetListenPort uint16
7374
Subsystems []codersdk.AgentSubsystem
@@ -126,6 +127,9 @@ func New(options Options) Agent {
126127
if options.ServiceBannerRefreshInterval == 0 {
127128
options.ServiceBannerRefreshInterval = 2 * time.Minute
128129
}
130+
if options.PortCacheDuration == 0 {
131+
options.PortCacheDuration = 1 * time.Second
132+
}
129133

130134
prometheusRegistry := options.PrometheusRegistry
131135
if prometheusRegistry == nil {
@@ -153,6 +157,7 @@ func New(options Options) Agent {
153157
lifecycleReported: make(chan codersdk.WorkspaceAgentLifecycle, 1),
154158
lifecycleStates: []agentsdk.PostLifecycleRequest{{State: codersdk.WorkspaceAgentLifecycleCreated}},
155159
ignorePorts: options.IgnorePorts,
160+
portCacheDuration: options.PortCacheDuration,
156161
connStatsChan: make(chan *agentsdk.Stats, 1),
157162
reportMetadataInterval: options.ReportMetadataInterval,
158163
serviceBannerRefreshInterval: options.ServiceBannerRefreshInterval,
@@ -181,8 +186,9 @@ type agent struct {
181186
// ignorePorts tells the api handler which ports to ignore when
182187
// listing all listening ports. This is helpful to hide ports that
183188
// are used by the agent, that the user does not care about.
184-
ignorePorts map[int]string
185-
subsystems []codersdk.AgentSubsystem
189+
ignorePorts map[int]string
190+
portCacheDuration time.Duration
191+
subsystems []codersdk.AgentSubsystem
186192

187193
reconnectingPTYs sync.Map
188194
reconnectingPTYTimeout time.Duration

agent/api.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,27 @@ func (a *agent) apiHandler() http.Handler {
2626
cpy[k] = b
2727
}
2828

29-
lp := &listeningPortsHandler{ignorePorts: cpy}
29+
cacheDuration := 1 * time.Second
30+
if a.portCacheDuration > 0 {
31+
cacheDuration = a.portCacheDuration
32+
}
33+
34+
lp := &listeningPortsHandler{
35+
ignorePorts: cpy,
36+
cacheDuration: cacheDuration,
37+
}
3038
r.Get("/api/v0/listening-ports", lp.handler)
3139

3240
return r
3341
}
3442

3543
type listeningPortsHandler struct {
36-
mut sync.Mutex
37-
ports []codersdk.WorkspaceAgentListeningPort
38-
mtime time.Time
39-
ignorePorts map[int]string
44+
ignorePorts map[int]string
45+
cacheDuration time.Duration
46+
47+
mut sync.Mutex
48+
ports []codersdk.WorkspaceAgentListeningPort
49+
mtime time.Time
4050
}
4151

4252
// handler returns a list of listening ports. This is tested by coderd's

agent/ports_supported.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func (lp *listeningPortsHandler) getListeningPorts() ([]codersdk.WorkspaceAgentL
1515
lp.mut.Lock()
1616
defer lp.mut.Unlock()
1717

18-
if time.Since(lp.mtime) < time.Second {
18+
if time.Since(lp.mtime) < lp.cacheDuration {
1919
// copy
2020
ports := make([]codersdk.WorkspaceAgentListeningPort, len(lp.ports))
2121
copy(ports, lp.ports)

coderd/workspaceagents_test.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"cdr.dev/slog"
2323
"cdr.dev/slog/sloggers/slogtest"
24+
"github.com/coder/coder/v2/agent"
2425
"github.com/coder/coder/v2/agent/agenttest"
2526
"github.com/coder/coder/v2/coderd"
2627
"github.com/coder/coder/v2/coderd/coderdtest"
@@ -551,7 +552,9 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) {
551552
},
552553
}},
553554
}).Do()
554-
_ = agenttest.New(t, client.URL, authToken)
555+
_ = agenttest.New(t, client.URL, authToken, func(o *agent.Options) {
556+
o.PortCacheDuration = time.Millisecond
557+
})
555558
resources := coderdtest.AwaitWorkspaceAgents(t, client, ws.ID)
556559
return client, uint16(coderdPort), resources[0].Agents[0].ID
557560
}
@@ -670,15 +673,21 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) {
670673

671674
// Close the listener and check that the port is no longer in the response.
672675
require.NoError(t, l.Close())
673-
time.Sleep(2 * time.Second) // avoid cache
674-
res, err = client.WorkspaceAgentListeningPorts(ctx, agentID)
675-
require.NoError(t, err)
676+
t.Log("checking for ports after listener close:")
677+
require.Eventually(t, func() bool {
678+
res, err = client.WorkspaceAgentListeningPorts(ctx, agentID)
679+
if !assert.NoError(t, err) {
680+
return false
681+
}
676682

677-
for _, port := range res.Ports {
678-
if port.Network == "tcp" && port.Port == lPort {
679-
t.Fatalf("expected to not find TCP port %d in response", lPort)
683+
for _, port := range res.Ports {
684+
if port.Network == "tcp" && port.Port == lPort {
685+
t.Logf("expected to not find TCP port %d in response", lPort)
686+
return false
687+
}
680688
}
681-
}
689+
return true
690+
}, testutil.WaitLong, testutil.IntervalMedium)
682691
})
683692

684693
t.Run("Filter", func(t *testing.T) {

0 commit comments

Comments
 (0)