mirror of
https://github.com/coder/coder.git
synced 2025-07-18 14:17:22 +00:00
chore: fix flake in listening ports test (#10833)
This commit is contained in:
@ -68,6 +68,7 @@ type Options struct {
|
|||||||
EnvironmentVariables map[string]string
|
EnvironmentVariables map[string]string
|
||||||
Logger slog.Logger
|
Logger slog.Logger
|
||||||
IgnorePorts map[int]string
|
IgnorePorts map[int]string
|
||||||
|
PortCacheDuration time.Duration
|
||||||
SSHMaxTimeout time.Duration
|
SSHMaxTimeout time.Duration
|
||||||
TailnetListenPort uint16
|
TailnetListenPort uint16
|
||||||
Subsystems []codersdk.AgentSubsystem
|
Subsystems []codersdk.AgentSubsystem
|
||||||
@ -126,6 +127,9 @@ func New(options Options) Agent {
|
|||||||
if options.ServiceBannerRefreshInterval == 0 {
|
if options.ServiceBannerRefreshInterval == 0 {
|
||||||
options.ServiceBannerRefreshInterval = 2 * time.Minute
|
options.ServiceBannerRefreshInterval = 2 * time.Minute
|
||||||
}
|
}
|
||||||
|
if options.PortCacheDuration == 0 {
|
||||||
|
options.PortCacheDuration = 1 * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
prometheusRegistry := options.PrometheusRegistry
|
prometheusRegistry := options.PrometheusRegistry
|
||||||
if prometheusRegistry == nil {
|
if prometheusRegistry == nil {
|
||||||
@ -153,6 +157,7 @@ func New(options Options) Agent {
|
|||||||
lifecycleReported: make(chan codersdk.WorkspaceAgentLifecycle, 1),
|
lifecycleReported: make(chan codersdk.WorkspaceAgentLifecycle, 1),
|
||||||
lifecycleStates: []agentsdk.PostLifecycleRequest{{State: codersdk.WorkspaceAgentLifecycleCreated}},
|
lifecycleStates: []agentsdk.PostLifecycleRequest{{State: codersdk.WorkspaceAgentLifecycleCreated}},
|
||||||
ignorePorts: options.IgnorePorts,
|
ignorePorts: options.IgnorePorts,
|
||||||
|
portCacheDuration: options.PortCacheDuration,
|
||||||
connStatsChan: make(chan *agentsdk.Stats, 1),
|
connStatsChan: make(chan *agentsdk.Stats, 1),
|
||||||
reportMetadataInterval: options.ReportMetadataInterval,
|
reportMetadataInterval: options.ReportMetadataInterval,
|
||||||
serviceBannerRefreshInterval: options.ServiceBannerRefreshInterval,
|
serviceBannerRefreshInterval: options.ServiceBannerRefreshInterval,
|
||||||
@ -182,6 +187,7 @@ type agent struct {
|
|||||||
// listing all listening ports. This is helpful to hide ports that
|
// listing all listening ports. This is helpful to hide ports that
|
||||||
// are used by the agent, that the user does not care about.
|
// are used by the agent, that the user does not care about.
|
||||||
ignorePorts map[int]string
|
ignorePorts map[int]string
|
||||||
|
portCacheDuration time.Duration
|
||||||
subsystems []codersdk.AgentSubsystem
|
subsystems []codersdk.AgentSubsystem
|
||||||
|
|
||||||
reconnectingPTYs sync.Map
|
reconnectingPTYs sync.Map
|
||||||
|
14
agent/api.go
14
agent/api.go
@ -26,17 +26,27 @@ func (a *agent) apiHandler() http.Handler {
|
|||||||
cpy[k] = b
|
cpy[k] = b
|
||||||
}
|
}
|
||||||
|
|
||||||
lp := &listeningPortsHandler{ignorePorts: cpy}
|
cacheDuration := 1 * time.Second
|
||||||
|
if a.portCacheDuration > 0 {
|
||||||
|
cacheDuration = a.portCacheDuration
|
||||||
|
}
|
||||||
|
|
||||||
|
lp := &listeningPortsHandler{
|
||||||
|
ignorePorts: cpy,
|
||||||
|
cacheDuration: cacheDuration,
|
||||||
|
}
|
||||||
r.Get("/api/v0/listening-ports", lp.handler)
|
r.Get("/api/v0/listening-ports", lp.handler)
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
type listeningPortsHandler struct {
|
type listeningPortsHandler struct {
|
||||||
|
ignorePorts map[int]string
|
||||||
|
cacheDuration time.Duration
|
||||||
|
|
||||||
mut sync.Mutex
|
mut sync.Mutex
|
||||||
ports []codersdk.WorkspaceAgentListeningPort
|
ports []codersdk.WorkspaceAgentListeningPort
|
||||||
mtime time.Time
|
mtime time.Time
|
||||||
ignorePorts map[int]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// handler returns a list of listening ports. This is tested by coderd's
|
// handler returns a list of listening ports. This is tested by coderd's
|
||||||
|
@ -15,7 +15,7 @@ func (lp *listeningPortsHandler) getListeningPorts() ([]codersdk.WorkspaceAgentL
|
|||||||
lp.mut.Lock()
|
lp.mut.Lock()
|
||||||
defer lp.mut.Unlock()
|
defer lp.mut.Unlock()
|
||||||
|
|
||||||
if time.Since(lp.mtime) < time.Second {
|
if time.Since(lp.mtime) < lp.cacheDuration {
|
||||||
// copy
|
// copy
|
||||||
ports := make([]codersdk.WorkspaceAgentListeningPort, len(lp.ports))
|
ports := make([]codersdk.WorkspaceAgentListeningPort, len(lp.ports))
|
||||||
copy(ports, lp.ports)
|
copy(ports, lp.ports)
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
"cdr.dev/slog"
|
"cdr.dev/slog"
|
||||||
"cdr.dev/slog/sloggers/slogtest"
|
"cdr.dev/slog/sloggers/slogtest"
|
||||||
|
"github.com/coder/coder/v2/agent"
|
||||||
"github.com/coder/coder/v2/agent/agenttest"
|
"github.com/coder/coder/v2/agent/agenttest"
|
||||||
"github.com/coder/coder/v2/coderd"
|
"github.com/coder/coder/v2/coderd"
|
||||||
"github.com/coder/coder/v2/coderd/coderdtest"
|
"github.com/coder/coder/v2/coderd/coderdtest"
|
||||||
@ -551,7 +552,9 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}).Do()
|
}).Do()
|
||||||
_ = agenttest.New(t, client.URL, authToken)
|
_ = agenttest.New(t, client.URL, authToken, func(o *agent.Options) {
|
||||||
|
o.PortCacheDuration = time.Millisecond
|
||||||
|
})
|
||||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, ws.ID)
|
resources := coderdtest.AwaitWorkspaceAgents(t, client, ws.ID)
|
||||||
return client, uint16(coderdPort), resources[0].Agents[0].ID
|
return client, uint16(coderdPort), resources[0].Agents[0].ID
|
||||||
}
|
}
|
||||||
@ -670,15 +673,21 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) {
|
|||||||
|
|
||||||
// Close the listener and check that the port is no longer in the response.
|
// Close the listener and check that the port is no longer in the response.
|
||||||
require.NoError(t, l.Close())
|
require.NoError(t, l.Close())
|
||||||
time.Sleep(2 * time.Second) // avoid cache
|
t.Log("checking for ports after listener close:")
|
||||||
|
require.Eventually(t, func() bool {
|
||||||
res, err = client.WorkspaceAgentListeningPorts(ctx, agentID)
|
res, err = client.WorkspaceAgentListeningPorts(ctx, agentID)
|
||||||
require.NoError(t, err)
|
if !assert.NoError(t, err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
for _, port := range res.Ports {
|
for _, port := range res.Ports {
|
||||||
if port.Network == "tcp" && port.Port == lPort {
|
if port.Network == "tcp" && port.Port == lPort {
|
||||||
t.Fatalf("expected to not find TCP port %d in response", lPort)
|
t.Logf("expected to not find TCP port %d in response", lPort)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
|
}, testutil.WaitLong, testutil.IntervalMedium)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Filter", func(t *testing.T) {
|
t.Run("Filter", func(t *testing.T) {
|
||||||
|
Reference in New Issue
Block a user