Skip to content

feat(support): fetch agent network info over tailnet #12577

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Mar 15, 2024
Next Next commit
refactor(support): move agent-related info to top level
  • Loading branch information
johnstcn committed Mar 14, 2024
commit 34d25a1672de5ffc2ed3237b9f2715cec8ca57c0
14 changes: 7 additions & 7 deletions cli/support.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func writeBundle(src *support.Bundle, dest *zip.Writer) error {
"network/netcheck_local.json": src.Network.NetcheckLocal,
"network/netcheck_remote.json": src.Network.NetcheckRemote,
"workspace/workspace.json": src.Workspace.Workspace,
"workspace/agent.json": src.Workspace.Agent,
"agent/agent.json": src.Agent.Agent,
"workspace/template.json": src.Workspace.Template,
"workspace/template_version.json": src.Workspace.TemplateVersion,
"workspace/parameters.json": src.Workspace.Parameters,
Expand All @@ -167,12 +167,12 @@ func writeBundle(src *support.Bundle, dest *zip.Writer) error {
}

for k, v := range map[string]string{
"network/coordinator_debug.html": src.Network.CoordinatorDebug,
"network/tailnet_debug.html": src.Network.TailnetDebug,
"workspace/build_logs.txt": humanizeBuildLogs(src.Workspace.BuildLogs),
"workspace/agent_startup_logs.txt": humanizeAgentLogs(src.Workspace.AgentStartupLogs),
"workspace/template_file.zip": string(templateVersionBytes),
"logs.txt": strings.Join(src.Logs, "\n"),
"network/coordinator_debug.html": src.Network.CoordinatorDebug,
"network/tailnet_debug.html": src.Network.TailnetDebug,
"workspace/build_logs.txt": humanizeBuildLogs(src.Workspace.BuildLogs),
"agent/startup_logs.txt": humanizeAgentLogs(src.Agent.StartupLogs),
"workspace/template_file.zip": string(templateVersionBytes),
"logs.txt": strings.Join(src.Logs, "\n"),
} {
f, err := dest.Create(k)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions cli/support_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,11 @@ func assertBundleContents(t *testing.T, path string) {
case "workspace/build_logs.txt":
bs := readBytesFromZip(t, f)
require.Contains(t, string(bs), "provision done")
case "workspace/agent.json":
case "agent/agent.json":
var v codersdk.WorkspaceAgent
decodeJSONFromZip(t, f, &v)
require.NotEmpty(t, v, "agent should not be empty")
case "workspace/agent_startup_logs.txt":
case "agent/startup_logs.txt":
bs := readBytesFromZip(t, f)
require.Contains(t, string(bs), "started up")
case "workspace/template.json":
Expand Down
89 changes: 54 additions & 35 deletions support/support.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Bundle struct {
Deployment Deployment `json:"deployment"`
Network Network `json:"network"`
Workspace Workspace `json:"workspace"`
Agent Agent `json:"agent"`
Logs []string `json:"logs"`
}

Expand All @@ -49,8 +50,11 @@ type Workspace struct {
TemplateVersion codersdk.TemplateVersion `json:"template_version"`
TemplateFileBase64 string `json:"template_file_base64"`
BuildLogs []codersdk.ProvisionerJobLog `json:"build_logs"`
Agent codersdk.WorkspaceAgent `json:"agent"`
AgentStartupLogs []codersdk.WorkspaceAgentLog `json:"startup_logs"`
}

type Agent struct {
Agent codersdk.WorkspaceAgent `json:"agent"`
StartupLogs []codersdk.WorkspaceAgentLog `json:"startup_logs"`
}

// Deps is a set of dependencies for discovering information
Expand Down Expand Up @@ -170,7 +174,7 @@ func NetworkInfo(ctx context.Context, client *codersdk.Client, log slog.Logger,
return n
}

func WorkspaceInfo(ctx context.Context, client *codersdk.Client, log slog.Logger, workspaceID, agentID uuid.UUID) Workspace {
func WorkspaceInfo(ctx context.Context, client *codersdk.Client, log slog.Logger, workspaceID uuid.UUID) Workspace {
var (
w Workspace
eg errgroup.Group
Expand All @@ -181,10 +185,6 @@ func WorkspaceInfo(ctx context.Context, client *codersdk.Client, log slog.Logger
return w
}

if agentID == uuid.Nil {
log.Error(ctx, "no agent id specified")
}

// dependency, cannot fetch concurrently
ws, err := client.Workspace(ctx, workspaceID)
if err != nil {
Expand All @@ -198,15 +198,6 @@ func WorkspaceInfo(ctx context.Context, client *codersdk.Client, log slog.Logger
}
w.Workspace = ws

eg.Go(func() error {
agt, err := client.WorkspaceAgent(ctx, agentID)
if err != nil {
return xerrors.Errorf("fetch workspace agent: %w", err)
}
w.Agent = agt
return nil
})

eg.Go(func() error {
buildLogCh, closer, err := client.WorkspaceBuildLogsAfter(ctx, ws.LatestBuild.ID, 0)
if err != nil {
Expand All @@ -221,24 +212,6 @@ func WorkspaceInfo(ctx context.Context, client *codersdk.Client, log slog.Logger
return nil
})

eg.Go(func() error {
if len(w.Workspace.LatestBuild.Resources) == 0 {
log.Warn(ctx, "workspace build has no resources")
return nil
}
agentLogCh, closer, err := client.WorkspaceAgentLogsAfter(ctx, agentID, 0, false)
if err != nil {
return xerrors.Errorf("fetch agent startup logs: %w", err)
}
defer closer.Close()
var logs []codersdk.WorkspaceAgentLog
for logChunk := range agentLogCh {
logs = append(w.AgentStartupLogs, logChunk...)
}
w.AgentStartupLogs = logs
return nil
})

eg.Go(func() error {
if w.Workspace.TemplateActiveVersionID == uuid.Nil {
return xerrors.Errorf("workspace has nil template active version id")
Expand Down Expand Up @@ -296,6 +269,47 @@ func WorkspaceInfo(ctx context.Context, client *codersdk.Client, log slog.Logger
return w
}

func AgentInfo(ctx context.Context, client *codersdk.Client, log slog.Logger, agentID uuid.UUID) Agent {
var (
a Agent
eg errgroup.Group
)

if agentID == uuid.Nil {
log.Error(ctx, "no agent id specified")
return a
}

eg.Go(func() error {
agt, err := client.WorkspaceAgent(ctx, agentID)
if err != nil {
return xerrors.Errorf("fetch workspace agent: %w", err)
}
a.Agent = agt
return nil
})

eg.Go(func() error {
agentLogCh, closer, err := client.WorkspaceAgentLogsAfter(ctx, agentID, 0, false)
if err != nil {
return xerrors.Errorf("fetch agent startup logs: %w", err)
}
defer closer.Close()
var logs []codersdk.WorkspaceAgentLog
for logChunk := range agentLogCh {
logs = append(logs, logChunk...)
}
a.StartupLogs = logs
return nil
})

if err := eg.Wait(); err != nil {
log.Error(ctx, "fetch agent information", slog.Error(err))
}

return a
}

// Run generates a support bundle with the given dependencies.
func Run(ctx context.Context, d *Deps) (*Bundle, error) {
var b Bundle
Expand Down Expand Up @@ -337,7 +351,7 @@ func Run(ctx context.Context, d *Deps) (*Bundle, error) {
return nil
})
eg.Go(func() error {
wi := WorkspaceInfo(ctx, d.Client, d.Log, d.WorkspaceID, d.AgentID)
wi := WorkspaceInfo(ctx, d.Client, d.Log, d.WorkspaceID)
b.Workspace = wi
return nil
})
Expand All @@ -346,6 +360,11 @@ func Run(ctx context.Context, d *Deps) (*Bundle, error) {
b.Network = ni
return nil
})
eg.Go(func() error {
ai := AgentInfo(ctx, d.Client, d.Log, d.AgentID)
b.Agent = ai
return nil
})

_ = eg.Wait()

Expand Down
4 changes: 2 additions & 2 deletions support/support_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ func TestRun(t *testing.T) {
require.NotNil(t, bun.Workspace.Workspace)
assertSanitizedWorkspace(t, bun.Workspace.Workspace)
require.NotEmpty(t, bun.Workspace.BuildLogs)
require.NotNil(t, bun.Workspace.Agent)
require.NotEmpty(t, bun.Workspace.AgentStartupLogs)
require.NotEmpty(t, bun.Workspace.Template)
require.NotEmpty(t, bun.Workspace.TemplateVersion)
require.NotEmpty(t, bun.Workspace.TemplateFileBase64)
require.NotNil(t, bun.Workspace.Parameters)
require.NotNil(t, bun.Agent.Agent)
require.NotEmpty(t, bun.Agent.StartupLogs)
require.NotEmpty(t, bun.Logs)
})

Expand Down