@@ -25,6 +25,7 @@ type AgentOptions struct {
25
25
Fetch func (ctx context.Context , agentID uuid.UUID ) (codersdk.WorkspaceAgent , error )
26
26
FetchLogs func (ctx context.Context , agentID uuid.UUID , after int64 , follow bool ) (<- chan []codersdk.WorkspaceAgentLog , io.Closer , error )
27
27
Wait bool // If true, wait for the agent to be ready (startup script).
28
+ DocsURL string
28
29
}
29
30
30
31
// Agent displays a spinning indicator that waits for a workspace agent to connect.
@@ -119,7 +120,7 @@ func Agent(ctx context.Context, writer io.Writer, agentID uuid.UUID, opts AgentO
119
120
if agent .Status == codersdk .WorkspaceAgentTimeout {
120
121
now := time .Now ()
121
122
sw .Log (now , codersdk .LogLevelInfo , "The workspace agent is having trouble connecting, wait for it to connect or restart your workspace." )
122
- sw .Log (now , codersdk .LogLevelInfo , troubleshootingMessage (agent , "https://coder.com/docs/ templates#agent-connection-issues" ))
123
+ sw .Log (now , codersdk .LogLevelInfo , troubleshootingMessage (agent , fmt . Sprintf ( "%s/ templates#agent-connection-issues", opts . DocsURL ) ))
123
124
for agent .Status == codersdk .WorkspaceAgentTimeout {
124
125
if agent , err = fetch (); err != nil {
125
126
return xerrors .Errorf ("fetch: %w" , err )
@@ -224,13 +225,13 @@ func Agent(ctx context.Context, writer io.Writer, agentID uuid.UUID, opts AgentO
224
225
sw .Fail (stage , safeDuration (sw , agent .ReadyAt , agent .StartedAt ))
225
226
// Use zero time (omitted) to separate these from the startup logs.
226
227
sw .Log (time.Time {}, codersdk .LogLevelWarn , "Warning: A startup script exited with an error and your workspace may be incomplete." )
227
- sw .Log (time.Time {}, codersdk .LogLevelWarn , troubleshootingMessage (agent , "https://coder.com/docs/ templates/troubleshooting #startup-script-exited-with-an-error" ))
228
+ sw .Log (time.Time {}, codersdk .LogLevelWarn , troubleshootingMessage (agent , fmt . Sprintf ( "%s/ templates#startup-script-exited-with-an-error", opts . DocsURL ) ))
228
229
default :
229
230
switch {
230
231
case agent .LifecycleState .Starting ():
231
232
// Use zero time (omitted) to separate these from the startup logs.
232
233
sw .Log (time.Time {}, codersdk .LogLevelWarn , "Notice: The startup scripts are still running and your workspace may be incomplete." )
233
- sw .Log (time.Time {}, codersdk .LogLevelWarn , troubleshootingMessage (agent , "https://coder.com/docs/ templates/troubleshooting #your-workspace-may-be-incomplete" ))
234
+ sw .Log (time.Time {}, codersdk .LogLevelWarn , troubleshootingMessage (agent , fmt . Sprintf ( "%s/ templates#your-workspace-may-be-incomplete", opts . DocsURL ) ))
234
235
// Note: We don't complete or fail the stage here, it's
235
236
// intentionally left open to indicate this stage didn't
236
237
// complete.
@@ -252,7 +253,7 @@ func Agent(ctx context.Context, writer io.Writer, agentID uuid.UUID, opts AgentO
252
253
stage := "The workspace agent lost connection"
253
254
sw .Start (stage )
254
255
sw .Log (time .Now (), codersdk .LogLevelWarn , "Wait for it to reconnect or restart your workspace." )
255
- sw .Log (time .Now (), codersdk .LogLevelWarn , troubleshootingMessage (agent , "https://coder.com/docs/ templates/troubleshooting #agent-connection-issues" ))
256
+ sw .Log (time .Now (), codersdk .LogLevelWarn , troubleshootingMessage (agent , fmt . Sprintf ( "%s/ templates#agent-connection-issues", opts . DocsURL ) ))
256
257
257
258
disconnectedAt := agent .DisconnectedAt
258
259
for agent .Status == codersdk .WorkspaceAgentDisconnected {
@@ -351,16 +352,16 @@ func PeerDiagnostics(w io.Writer, d tailnet.PeerDiagnostics) {
351
352
}
352
353
353
354
type ConnDiags struct {
354
- ConnInfo workspacesdk.AgentConnectionInfo
355
- PingP2P bool
356
- DisableDirect bool
357
- LocalNetInfo * tailcfg.NetInfo
358
- LocalInterfaces * healthsdk.InterfacesReport
359
- AgentNetcheck * healthsdk.AgentNetcheckReport
360
- ClientIPIsAWS bool
361
- AgentIPIsAWS bool
362
- Verbose bool
363
- // TODO: More diagnostics
355
+ ConnInfo workspacesdk.AgentConnectionInfo
356
+ PingP2P bool
357
+ DisableDirect bool
358
+ LocalNetInfo * tailcfg.NetInfo
359
+ LocalInterfaces * healthsdk.InterfacesReport
360
+ AgentNetcheck * healthsdk.AgentNetcheckReport
361
+ ClientIPIsAWS bool
362
+ AgentIPIsAWS bool
363
+ Verbose bool
364
+ TroubleshootingURL string
364
365
}
365
366
366
367
func (d ConnDiags ) Write (w io.Writer ) {
@@ -395,7 +396,7 @@ func (d ConnDiags) splitDiagnostics() (general, client, agent []string) {
395
396
agent = append (agent , msg .Message )
396
397
}
397
398
if len (d .AgentNetcheck .Interfaces .Warnings ) > 0 {
398
- agent [len (agent )- 1 ] += " \n https://coder.com/docs/networking/troubleshooting #low-mtu"
399
+ agent [len (agent )- 1 ] += fmt . Sprintf ( " \n %s #low-mtu", d . TroubleshootingURL )
399
400
}
400
401
}
401
402
@@ -404,7 +405,7 @@ func (d ConnDiags) splitDiagnostics() (general, client, agent []string) {
404
405
client = append (client , msg .Message )
405
406
}
406
407
if len (d .LocalInterfaces .Warnings ) > 0 {
407
- client [len (client )- 1 ] += " \n https://coder.com/docs/networking/troubleshooting #low-mtu"
408
+ client [len (client )- 1 ] += fmt . Sprintf ( " \n %s #low-mtu", d . TroubleshootingURL )
408
409
}
409
410
}
410
411
@@ -420,45 +421,45 @@ func (d ConnDiags) splitDiagnostics() (general, client, agent []string) {
420
421
}
421
422
422
423
if d .ConnInfo .DisableDirectConnections {
423
- general = append (general , "❗ Your Coder administrator has blocked direct connections \n " +
424
- " https://coder.com/docs/networking/troubleshooting #disabled-deployment-wide" )
424
+ general = append (general ,
425
+ fmt . Sprintf ( "❗ Your Coder administrator has blocked direct connections \n %s #disabled-deployment-wide", d . TroubleshootingURL ) )
425
426
if ! d .Verbose {
426
427
return general , client , agent
427
428
}
428
429
}
429
430
430
431
if ! d .ConnInfo .DERPMap .HasSTUN () {
431
- general = append (general , "❗ The DERP map is not configured to use STUN \n " +
432
- " https://coder.com/docs/networking/troubleshooting #no-stun-servers" )
432
+ general = append (general ,
433
+ fmt . Sprintf ( "❗ The DERP map is not configured to use STUN \n %s #no-stun-servers", d . TroubleshootingURL ) )
433
434
} else if d .LocalNetInfo != nil && ! d .LocalNetInfo .UDP {
434
- client = append (client , "Client could not connect to STUN over UDP \n " +
435
- " https://coder.com/docs/networking/troubleshooting #udp-blocked" )
435
+ client = append (client ,
436
+ fmt . Sprintf ( "Client could not connect to STUN over UDP \n %s #udp-blocked", d . TroubleshootingURL ) )
436
437
}
437
438
438
439
if d .LocalNetInfo != nil && d .LocalNetInfo .MappingVariesByDestIP .EqualBool (true ) {
439
- client = append (client , "Client is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers \n " +
440
- " https://coder.com/docs/networking/troubleshooting#Endpoint-Dependent-Nat-Hard-NAT" )
440
+ client = append (client ,
441
+ fmt . Sprintf ( "Client is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers \n %s#endpoint-dependent-nat-hard-nat" , d . TroubleshootingURL ) )
441
442
}
442
443
443
444
if d .AgentNetcheck != nil && d .AgentNetcheck .NetInfo != nil {
444
445
if d .AgentNetcheck .NetInfo .MappingVariesByDestIP .EqualBool (true ) {
445
- agent = append (agent , "Agent is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers \n " +
446
- " https://coder.com/docs/networking/troubleshooting#Endpoint-Dependent-Nat-Hard-NAT" )
446
+ agent = append (agent ,
447
+ fmt . Sprintf ( "Agent is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers \n %s#endpoint-dependent-nat-hard-nat" , d . TroubleshootingURL ) )
447
448
}
448
449
if ! d .AgentNetcheck .NetInfo .UDP {
449
- agent = append (agent , "Agent could not connect to STUN over UDP \n " +
450
- " https://coder.com/docs/networking/troubleshooting #udp-blocked" )
450
+ agent = append (agent ,
451
+ fmt . Sprintf ( "Agent could not connect to STUN over UDP \n %s #udp-blocked", d . TroubleshootingURL ) )
451
452
}
452
453
}
453
454
454
455
if d .ClientIPIsAWS {
455
- client = append (client , "Client IP address is within an AWS range (AWS uses hard NAT) \n " +
456
- " https://coder.com/docs/networking/troubleshooting#Endpoint-Dependent-Nat-Hard-NAT" )
456
+ client = append (client ,
457
+ fmt . Sprintf ( "Client IP address is within an AWS range (AWS uses hard NAT) \n %s#endpoint-dependent-nat-hard-nat" , d . TroubleshootingURL ) )
457
458
}
458
459
459
460
if d .AgentIPIsAWS {
460
- agent = append (agent , "Agent IP address is within an AWS range (AWS uses hard NAT) \n " +
461
- " https://coder.com/docs/networking/troubleshooting#Endpoint-Dependent-Nat-Hard-NAT" )
461
+ agent = append (agent ,
462
+ fmt . Sprintf ( "Agent IP address is within an AWS range (AWS uses hard NAT) \n %s#endpoint-dependent-nat-hard-nat" , d . TroubleshootingURL ) )
462
463
}
463
464
return general , client , agent
464
465
}
0 commit comments