88 "fmt"
99 "hash/fnv"
1010 "io"
11+ "maps"
1112 "net"
1213 "net/http"
1314 "net/netip"
@@ -70,16 +71,21 @@ const (
7071)
7172
7273type Options struct {
73- Filesystem afero.Fs
74- LogDir string
75- TempDir string
76- ScriptDataDir string
77- Client Client
78- ReconnectingPTYTimeout time.Duration
79- EnvironmentVariables map [string ]string
80- Logger slog.Logger
81- IgnorePorts map [int ]string
82- PortCacheDuration time.Duration
74+ Filesystem afero.Fs
75+ LogDir string
76+ TempDir string
77+ ScriptDataDir string
78+ Client Client
79+ ReconnectingPTYTimeout time.Duration
80+ EnvironmentVariables map [string ]string
81+ Logger slog.Logger
82+ // IgnorePorts tells the api handler which ports to ignore when
83+ // listing all listening ports. This is helpful to hide ports that
84+ // are used by the agent, that the user does not care about.
85+ IgnorePorts map [int ]string
86+ // ListeningPortsGetter is used to get the list of listening ports. Only
87+ // tests should set this. If unset, a default that queries the OS will be used.
88+ ListeningPortsGetter ListeningPortsGetter
8389 SSHMaxTimeout time.Duration
8490 TailnetListenPort uint16
8591 Subsystems []codersdk.AgentSubsystem
@@ -137,9 +143,7 @@ func New(options Options) Agent {
137143 if options .ServiceBannerRefreshInterval == 0 {
138144 options .ServiceBannerRefreshInterval = 2 * time .Minute
139145 }
140- if options .PortCacheDuration == 0 {
141- options .PortCacheDuration = 1 * time .Second
142- }
146+
143147 if options .Clock == nil {
144148 options .Clock = quartz .NewReal ()
145149 }
@@ -153,30 +157,38 @@ func New(options Options) Agent {
153157 options .Execer = agentexec .DefaultExecer
154158 }
155159
160+ if options .ListeningPortsGetter == nil {
161+ options .ListeningPortsGetter = & osListeningPortsGetter {
162+ cacheDuration : 1 * time .Second ,
163+ }
164+ }
165+
156166 hardCtx , hardCancel := context .WithCancel (context .Background ())
157167 gracefulCtx , gracefulCancel := context .WithCancel (hardCtx )
158168 a := & agent {
159- clock : options .Clock ,
160- tailnetListenPort : options .TailnetListenPort ,
161- reconnectingPTYTimeout : options .ReconnectingPTYTimeout ,
162- logger : options .Logger ,
163- gracefulCtx : gracefulCtx ,
164- gracefulCancel : gracefulCancel ,
165- hardCtx : hardCtx ,
166- hardCancel : hardCancel ,
167- coordDisconnected : make (chan struct {}),
168- environmentVariables : options .EnvironmentVariables ,
169- client : options .Client ,
170- filesystem : options .Filesystem ,
171- logDir : options .LogDir ,
172- tempDir : options .TempDir ,
173- scriptDataDir : options .ScriptDataDir ,
174- lifecycleUpdate : make (chan struct {}, 1 ),
175- lifecycleReported : make (chan codersdk.WorkspaceAgentLifecycle , 1 ),
176- lifecycleStates : []agentsdk.PostLifecycleRequest {{State : codersdk .WorkspaceAgentLifecycleCreated }},
177- reportConnectionsUpdate : make (chan struct {}, 1 ),
178- ignorePorts : options .IgnorePorts ,
179- portCacheDuration : options .PortCacheDuration ,
169+ clock : options .Clock ,
170+ tailnetListenPort : options .TailnetListenPort ,
171+ reconnectingPTYTimeout : options .ReconnectingPTYTimeout ,
172+ logger : options .Logger ,
173+ gracefulCtx : gracefulCtx ,
174+ gracefulCancel : gracefulCancel ,
175+ hardCtx : hardCtx ,
176+ hardCancel : hardCancel ,
177+ coordDisconnected : make (chan struct {}),
178+ environmentVariables : options .EnvironmentVariables ,
179+ client : options .Client ,
180+ filesystem : options .Filesystem ,
181+ logDir : options .LogDir ,
182+ tempDir : options .TempDir ,
183+ scriptDataDir : options .ScriptDataDir ,
184+ lifecycleUpdate : make (chan struct {}, 1 ),
185+ lifecycleReported : make (chan codersdk.WorkspaceAgentLifecycle , 1 ),
186+ lifecycleStates : []agentsdk.PostLifecycleRequest {{State : codersdk .WorkspaceAgentLifecycleCreated }},
187+ reportConnectionsUpdate : make (chan struct {}, 1 ),
188+ listeningPortsHandler : listeningPortsHandler {
189+ getter : options .ListeningPortsGetter ,
190+ ignorePorts : maps .Clone (options .IgnorePorts ),
191+ },
180192 reportMetadataInterval : options .ReportMetadataInterval ,
181193 announcementBannersRefreshInterval : options .ServiceBannerRefreshInterval ,
182194 sshMaxTimeout : options .SSHMaxTimeout ,
@@ -202,20 +214,16 @@ func New(options Options) Agent {
202214}
203215
204216type agent struct {
205- clock quartz.Clock
206- logger slog.Logger
207- client Client
208- tailnetListenPort uint16
209- filesystem afero.Fs
210- logDir string
211- tempDir string
212- scriptDataDir string
213- // ignorePorts tells the api handler which ports to ignore when
214- // listing all listening ports. This is helpful to hide ports that
215- // are used by the agent, that the user does not care about.
216- ignorePorts map [int ]string
217- portCacheDuration time.Duration
218- subsystems []codersdk.AgentSubsystem
217+ clock quartz.Clock
218+ logger slog.Logger
219+ client Client
220+ tailnetListenPort uint16
221+ filesystem afero.Fs
222+ logDir string
223+ tempDir string
224+ scriptDataDir string
225+ listeningPortsHandler listeningPortsHandler
226+ subsystems []codersdk.AgentSubsystem
219227
220228 reconnectingPTYTimeout time.Duration
221229 reconnectingPTYServer * reconnectingpty.Server
0 commit comments