Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b567c55

Browse files
committed
Add testcase for cliui.Agent troubleshooting message
1 parent 2bf20be commit b567c55

File tree

3 files changed

+71
-27
lines changed

3 files changed

+71
-27
lines changed

cli/cliui/agent.go

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,11 @@ func Agent(ctx context.Context, writer io.Writer, opts AgentOptions) error {
3535
if err != nil {
3636
return xerrors.Errorf("fetch: %w", err)
3737
}
38-
switch agent.Status {
39-
case codersdk.WorkspaceAgentConnected:
38+
39+
if agent.Status == codersdk.WorkspaceAgentConnected {
4040
return nil
41-
case codersdk.WorkspaceAgentTimeout, codersdk.WorkspaceAgentDisconnected:
42-
opts.WarnInterval = 0
4341
}
42+
4443
spin := spinner.New(spinner.CharSets[78], 100*time.Millisecond, spinner.WithColor("fgHiGreen"))
4544
spin.Writer = writer
4645
spin.ForceOutput = true
@@ -65,42 +64,54 @@ func Agent(ctx context.Context, writer io.Writer, opts AgentOptions) error {
6564
os.Exit(1)
6665
}()
6766

68-
ticker := time.NewTicker(opts.FetchInterval)
69-
defer ticker.Stop()
70-
timer := time.NewTimer(opts.WarnInterval)
71-
defer timer.Stop()
72-
go func() {
73-
select {
74-
case <-ctx.Done():
75-
return
76-
case <-timer.C:
77-
}
67+
warningShown := false
68+
warnAfter := time.NewTimer(opts.WarnInterval)
69+
defer warnAfter.Stop()
70+
showWarning := func() {
71+
warnAfter.Stop()
72+
7873
resourceMutex.Lock()
7974
defer resourceMutex.Unlock()
75+
if warningShown {
76+
return
77+
}
78+
warningShown = true
8079

8180
message := waitingMessage(agent)
8281
// This saves the cursor position, then defers clearing from the cursor
8382
// position to the end of the screen.
8483
_, _ = fmt.Fprintf(writer, "\033[s\r\033[2K%s\n\n", Styles.Paragraph.Render(Styles.Prompt.String()+message))
8584
defer fmt.Fprintf(writer, "\033[u\033[J")
85+
}
86+
go func() {
87+
select {
88+
case <-ctx.Done():
89+
case <-warnAfter.C:
90+
showWarning()
91+
}
8692
}()
93+
94+
fetchInterval := time.NewTicker(opts.FetchInterval)
95+
defer fetchInterval.Stop()
8796
for {
8897
select {
8998
case <-ctx.Done():
9099
return ctx.Err()
91-
case <-ticker.C:
100+
case <-fetchInterval.C:
92101
}
93102
resourceMutex.Lock()
94103
agent, err = opts.Fetch(ctx)
95104
if err != nil {
96-
return xerrors.Errorf("fetch: %w", err)
97-
}
98-
if agent.Status != codersdk.WorkspaceAgentConnected {
99105
resourceMutex.Unlock()
100-
continue
106+
return xerrors.Errorf("fetch: %w", err)
101107
}
102108
resourceMutex.Unlock()
103-
return nil
109+
switch agent.Status {
110+
case codersdk.WorkspaceAgentConnected:
111+
return nil
112+
case codersdk.WorkspaceAgentTimeout, codersdk.WorkspaceAgentDisconnected:
113+
showWarning()
114+
}
104115
}
105116
}
106117

cli/speedtest_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func TestSpeedtest(t *testing.T) {
2020
if testing.Short() {
2121
t.Skip("This test takes a minimum of 5ms per a hardcoded value in Tailscale!")
2222
}
23-
client, workspace, agentToken := setupWorkspaceForAgent(t)
23+
client, workspace, agentToken := setupWorkspaceForAgent(t, nil)
2424
agentClient := codersdk.New(client.URL)
2525
agentClient.SessionToken = agentToken
2626
agentCloser := agent.New(agent.Options{

cli/ssh_test.go

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,13 @@ import (
3131
"github.com/coder/coder/testutil"
3232
)
3333

34-
func setupWorkspaceForAgent(t *testing.T) (*codersdk.Client, codersdk.Workspace, string) {
34+
func setupWorkspaceForAgent(t *testing.T, mutate func([]*proto.Agent) []*proto.Agent) (*codersdk.Client, codersdk.Workspace, string) {
3535
t.Helper()
36+
if mutate == nil {
37+
mutate = func(a []*proto.Agent) []*proto.Agent {
38+
return a
39+
}
40+
}
3641
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
3742
user := coderdtest.CreateFirstUser(t, client)
3843
agentToken := uuid.NewString()
@@ -45,12 +50,12 @@ func setupWorkspaceForAgent(t *testing.T) (*codersdk.Client, codersdk.Workspace,
4550
Resources: []*proto.Resource{{
4651
Name: "dev",
4752
Type: "google_compute_instance",
48-
Agents: []*proto.Agent{{
53+
Agents: mutate([]*proto.Agent{{
4954
Id: uuid.NewString(),
5055
Auth: &proto.Agent_Token{
5156
Token: agentToken,
5257
},
53-
}},
58+
}}),
5459
}},
5560
},
5661
},
@@ -69,7 +74,7 @@ func TestSSH(t *testing.T) {
6974
t.Run("ImmediateExit", func(t *testing.T) {
7075
t.Parallel()
7176

72-
client, workspace, agentToken := setupWorkspaceForAgent(t)
77+
client, workspace, agentToken := setupWorkspaceForAgent(t, nil)
7378
cmd, root := clitest.New(t, "ssh", workspace.Name)
7479
clitest.SetupConfig(t, client, root)
7580
pty := ptytest.New(t)
@@ -100,9 +105,37 @@ func TestSSH(t *testing.T) {
100105
pty.WriteLine("exit")
101106
<-cmdDone
102107
})
108+
t.Run("ShowTroubleshootingURLAfterTimeout", func(t *testing.T) {
109+
t.Parallel()
110+
111+
wantURL := "https://example.com/troubleshoot"
112+
client, workspace, _ := setupWorkspaceForAgent(t, func(a []*proto.Agent) []*proto.Agent {
113+
// One second is the lowest we can go.
114+
a[0].ConnectionTimeout = 1
115+
a[0].TroubleshootingUrl = wantURL
116+
return a
117+
})
118+
cmd, root := clitest.New(t, "ssh", workspace.Name)
119+
clitest.SetupConfig(t, client, root)
120+
pty := ptytest.New(t)
121+
cmd.SetIn(pty.Input())
122+
cmd.SetErr(pty.Output())
123+
cmd.SetOut(pty.Output())
124+
125+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
126+
defer cancel()
127+
128+
cmdDone := tGo(t, func() {
129+
err := cmd.ExecuteContext(ctx)
130+
assert.ErrorIs(t, err, context.Canceled)
131+
})
132+
pty.ExpectMatch(wantURL)
133+
cancel()
134+
<-cmdDone
135+
})
103136
t.Run("Stdio", func(t *testing.T) {
104137
t.Parallel()
105-
client, workspace, agentToken := setupWorkspaceForAgent(t)
138+
client, workspace, agentToken := setupWorkspaceForAgent(t, nil)
106139
_, _ = tGoContext(t, func(ctx context.Context) {
107140
// Run this async so the SSH command has to wait for
108141
// the build and agent to connect!
@@ -171,7 +204,7 @@ func TestSSH(t *testing.T) {
171204

172205
t.Parallel()
173206

174-
client, workspace, agentToken := setupWorkspaceForAgent(t)
207+
client, workspace, agentToken := setupWorkspaceForAgent(t, nil)
175208

176209
agentClient := codersdk.New(client.URL)
177210
agentClient.SessionToken = agentToken

0 commit comments

Comments
 (0)