Skip to content

Commit 2abc1cd

Browse files
authored
feat(support): fetch agent network info over tailnet (#12577)
Adds agent-related information to support bundle command.
1 parent 653ddcc commit 2abc1cd

File tree

4 files changed

+265
-90
lines changed

4 files changed

+265
-90
lines changed

cli/support.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,19 @@ func findAgent(agentName string, haystack []codersdk.WorkspaceResource) (*coders
137137
}
138138

139139
func writeBundle(src *support.Bundle, dest *zip.Writer) error {
140+
// We JSON-encode the following:
140141
for k, v := range map[string]any{
141142
"deployment/buildinfo.json": src.Deployment.BuildInfo,
142143
"deployment/config.json": src.Deployment.Config,
143144
"deployment/experiments.json": src.Deployment.Experiments,
144145
"deployment/health.json": src.Deployment.HealthReport,
145-
"network/netcheck_local.json": src.Network.NetcheckLocal,
146-
"network/netcheck_remote.json": src.Network.NetcheckRemote,
146+
"network/netcheck.json": src.Network.Netcheck,
147147
"workspace/workspace.json": src.Workspace.Workspace,
148-
"workspace/agent.json": src.Workspace.Agent,
148+
"agent/agent.json": src.Agent.Agent,
149+
"agent/listening_ports.json": src.Agent.ListeningPorts,
150+
"agent/manifest.json": src.Agent.Manifest,
151+
"agent/peer_diagnostics.json": src.Agent.PeerDiagnostics,
152+
"agent/ping_result.json": src.Agent.PingResult,
149153
"workspace/template.json": src.Workspace.Template,
150154
"workspace/template_version.json": src.Workspace.TemplateVersion,
151155
"workspace/parameters.json": src.Workspace.Parameters,
@@ -166,13 +170,16 @@ func writeBundle(src *support.Bundle, dest *zip.Writer) error {
166170
return xerrors.Errorf("decode template zip from base64")
167171
}
168172

173+
// The below we just write as we have them:
169174
for k, v := range map[string]string{
170-
"network/coordinator_debug.html": src.Network.CoordinatorDebug,
171-
"network/tailnet_debug.html": src.Network.TailnetDebug,
172-
"workspace/build_logs.txt": humanizeBuildLogs(src.Workspace.BuildLogs),
173-
"workspace/agent_startup_logs.txt": humanizeAgentLogs(src.Workspace.AgentStartupLogs),
174-
"workspace/template_file.zip": string(templateVersionBytes),
175-
"logs.txt": strings.Join(src.Logs, "\n"),
175+
"network/coordinator_debug.html": src.Network.CoordinatorDebug,
176+
"network/tailnet_debug.html": src.Network.TailnetDebug,
177+
"workspace/build_logs.txt": humanizeBuildLogs(src.Workspace.BuildLogs),
178+
"agent/logs.txt": string(src.Agent.Logs),
179+
"agent/magicsock.html": string(src.Agent.MagicsockHTML),
180+
"agent/startup_logs.txt": humanizeAgentLogs(src.Agent.StartupLogs),
181+
"workspace/template_file.zip": string(templateVersionBytes),
182+
"logs.txt": strings.Join(src.Logs, "\n"),
176183
} {
177184
f, err := dest.Create(k)
178185
if err != nil {

cli/support_test.go

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,26 @@ import (
44
"archive/zip"
55
"encoding/json"
66
"io"
7+
"os"
78
"path/filepath"
89
"runtime"
910
"testing"
1011
"time"
1112

13+
"tailscale.com/ipn/ipnstate"
14+
1215
"github.com/stretchr/testify/require"
1316

17+
"github.com/coder/coder/v2/agent"
18+
"github.com/coder/coder/v2/agent/agenttest"
1419
"github.com/coder/coder/v2/cli/clitest"
1520
"github.com/coder/coder/v2/coderd/coderdtest"
1621
"github.com/coder/coder/v2/coderd/database"
1722
"github.com/coder/coder/v2/coderd/database/dbfake"
1823
"github.com/coder/coder/v2/coderd/database/dbtime"
1924
"github.com/coder/coder/v2/codersdk"
25+
"github.com/coder/coder/v2/codersdk/agentsdk"
26+
"github.com/coder/coder/v2/tailnet"
2027
"github.com/coder/coder/v2/testutil"
2128
)
2229

@@ -37,7 +44,14 @@ func TestSupportBundle(t *testing.T) {
3744
}).WithAgent().Do()
3845
ws, err := client.Workspace(ctx, r.Workspace.ID)
3946
require.NoError(t, err)
40-
agt := ws.LatestBuild.Resources[0].Agents[0]
47+
tempDir := t.TempDir()
48+
logPath := filepath.Join(tempDir, "coder-agent.log")
49+
require.NoError(t, os.WriteFile(logPath, []byte("hello from the agent"), 0o600))
50+
agt := agenttest.New(t, client.URL, r.AgentToken, func(o *agent.Options) {
51+
o.LogDir = tempDir
52+
})
53+
defer agt.Close()
54+
coderdtest.NewWorkspaceAgentWaiter(t, client, r.Workspace.ID).Wait()
4155

4256
// Insert a provisioner job log
4357
_, err = db.InsertProvisionerJobLogs(ctx, database.InsertProvisionerJobLogsParams{
@@ -51,7 +65,7 @@ func TestSupportBundle(t *testing.T) {
5165
require.NoError(t, err)
5266
// Insert an agent log
5367
_, err = db.InsertWorkspaceAgentLogs(ctx, database.InsertWorkspaceAgentLogsParams{
54-
AgentID: agt.ID,
68+
AgentID: ws.LatestBuild.Resources[0].Agents[0].ID,
5569
CreatedAt: dbtime.Now(),
5670
Output: []string{"started up"},
5771
Level: []database.LogLevel{database.LogLevelInfo},
@@ -141,22 +155,44 @@ func assertBundleContents(t *testing.T, path string) {
141155
case "network/tailnet_debug.html":
142156
bs := readBytesFromZip(t, f)
143157
require.NotEmpty(t, bs, "tailnet debug should not be empty")
144-
case "network/netcheck_local.json", "network/netcheck_remote.json":
145-
// TODO: setup fake agent?
146-
bs := readBytesFromZip(t, f)
147-
require.NotEmpty(t, bs, "netcheck should not be empty")
158+
case "network/netcheck.json":
159+
var v codersdk.WorkspaceAgentConnectionInfo
160+
decodeJSONFromZip(t, f, &v)
161+
require.NotEmpty(t, v, "connection info should not be empty")
148162
case "workspace/workspace.json":
149163
var v codersdk.Workspace
150164
decodeJSONFromZip(t, f, &v)
151165
require.NotEmpty(t, v, "workspace should not be empty")
152166
case "workspace/build_logs.txt":
153167
bs := readBytesFromZip(t, f)
154168
require.Contains(t, string(bs), "provision done")
155-
case "workspace/agent.json":
169+
case "agent/agent.json":
156170
var v codersdk.WorkspaceAgent
157171
decodeJSONFromZip(t, f, &v)
158172
require.NotEmpty(t, v, "agent should not be empty")
159-
case "workspace/agent_startup_logs.txt":
173+
case "agent/listening_ports.json":
174+
var v codersdk.WorkspaceAgentListeningPortsResponse
175+
decodeJSONFromZip(t, f, &v)
176+
require.NotEmpty(t, v, "agent listening ports should not be empty")
177+
case "agent/logs.txt":
178+
bs := readBytesFromZip(t, f)
179+
require.NotEmpty(t, bs, "logs should not be empty")
180+
case "agent/magicsock.html":
181+
bs := readBytesFromZip(t, f)
182+
require.NotEmpty(t, bs, "agent magicsock should not be empty")
183+
case "agent/manifest.json":
184+
var v agentsdk.Manifest
185+
decodeJSONFromZip(t, f, &v)
186+
require.NotEmpty(t, v, "agent manifest should not be empty")
187+
case "agent/peer_diagnostics.json":
188+
var v *tailnet.PeerDiagnostics
189+
decodeJSONFromZip(t, f, &v)
190+
require.NotEmpty(t, v, "peer diagnostics should not be empty")
191+
case "agent/ping_result.json":
192+
var v *ipnstate.PingResult
193+
decodeJSONFromZip(t, f, &v)
194+
require.NotEmpty(t, v, "ping result should not be empty")
195+
case "agent/startup_logs.txt":
160196
bs := readBytesFromZip(t, f)
161197
require.Contains(t, string(bs), "started up")
162198
case "workspace/template.json":
@@ -178,7 +214,7 @@ func assertBundleContents(t *testing.T, path string) {
178214
bs := readBytesFromZip(t, f)
179215
require.NotEmpty(t, bs, "logs should not be empty")
180216
default:
181-
require.Failf(t, "unexpected file in bundle: %q", f.Name)
217+
require.Failf(t, "unexpected file in bundle", f.Name)
182218
}
183219
}
184220
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy