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

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Move license retrieval to DeploymentInfo, refactor license formatting…
… and catch errors
  • Loading branch information
kacpersaw committed Jun 23, 2025
commit 2951c2df8ea900d668ca67182ca5bcc2c6d1ddcd
22 changes: 21 additions & 1 deletion cli/support.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cli
import (
"archive/zip"
"bytes"
"context"
"encoding/base64"
"encoding/json"
"fmt"
Expand All @@ -13,6 +14,8 @@ import (
"text/tabwriter"
"time"

"github.com/coder/coder/v2/cli/cliutil"

"github.com/google/uuid"
"golang.org/x/xerrors"

Expand Down Expand Up @@ -303,6 +306,11 @@ func writeBundle(src *support.Bundle, dest *zip.Writer) error {
return xerrors.Errorf("decode template zip from base64")
}

licenseStatus, err := humanizeLicenses(src.Deployment.Licenses)
if err != nil {
return xerrors.Errorf("format license status: %w", err)
}

// The below we just write as we have them:
for k, v := range map[string]string{
"agent/logs.txt": string(src.Agent.Logs),
Expand All @@ -316,7 +324,7 @@ func writeBundle(src *support.Bundle, dest *zip.Writer) error {
"network/tailnet_debug.html": src.Network.TailnetDebug,
"workspace/build_logs.txt": humanizeBuildLogs(src.Workspace.BuildLogs),
"workspace/template_file.zip": string(templateVersionBytes),
"license-status.txt": src.LicenseStatus,
"license-status.txt": licenseStatus,
} {
f, err := dest.Create(k)
if err != nil {
Expand Down Expand Up @@ -361,3 +369,15 @@ func humanizeBuildLogs(ls []codersdk.ProvisionerJobLog) string {
_ = tw.Flush()
return buf.String()
}

func humanizeLicenses(licenses []codersdk.License) (string, error) {
formatter := cliutil.NewLicenseFormatter(cliutil.LicenseFormatterOpts{
Sanitize: true,
})

if len(licenses) == 0 {
return "No licenses found", nil
}

return formatter.Format(context.Background(), licenses)
}
57 changes: 22 additions & 35 deletions support/support.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import (
"net/http/httptest"
"strings"

"github.com/coder/coder/v2/cli/cliutil"

"github.com/google/uuid"
"golang.org/x/sync/errgroup"
"golang.org/x/xerrors"
Expand All @@ -32,20 +30,20 @@ import (
// Even though we do attempt to sanitize data, it may still contain
// sensitive information and should thus be treated as secret.
type Bundle struct {
Deployment Deployment `json:"deployment"`
Network Network `json:"network"`
Workspace Workspace `json:"workspace"`
Agent Agent `json:"agent"`
LicenseStatus string
Logs []string `json:"logs"`
CLILogs []byte `json:"cli_logs"`
Deployment Deployment `json:"deployment"`
Network Network `json:"network"`
Workspace Workspace `json:"workspace"`
Agent Agent `json:"agent"`
Logs []string `json:"logs"`
CLILogs []byte `json:"cli_logs"`
}

type Deployment struct {
BuildInfo *codersdk.BuildInfoResponse `json:"build"`
Config *codersdk.DeploymentConfig `json:"config"`
Experiments codersdk.Experiments `json:"experiments"`
HealthReport *healthsdk.HealthcheckReport `json:"health_report"`
Licenses []codersdk.License `json:"licenses"`
}

type Network struct {
Expand Down Expand Up @@ -141,6 +139,21 @@ func DeploymentInfo(ctx context.Context, client *codersdk.Client, log slog.Logge
return nil
})

eg.Go(func() error {
licenses, err := client.Licenses(ctx)
if err != nil {
// Ignore 404 because AGPL doesn't have this endpoint
if cerr, ok := codersdk.AsError(err); ok && cerr.StatusCode() != http.StatusNotFound {
return xerrors.Errorf("fetch license status: %w", err)
}
}
if licenses == nil {
licenses = make([]codersdk.License, 0)
}
d.Licenses = licenses
return nil
})

if err := eg.Wait(); err != nil {
log.Error(ctx, "fetch deployment information", slog.Error(err))
}
Expand Down Expand Up @@ -354,27 +367,6 @@ func AgentInfo(ctx context.Context, client *codersdk.Client, log slog.Logger, ag
return a
}

func LicenseStatus(ctx context.Context, client *codersdk.Client, log slog.Logger) string {
licenses, err := client.Licenses(ctx)
if err != nil {
log.Warn(ctx, "fetch licenses", slog.Error(err))
return "No licenses found"
}
// Ensure that we print "[]" instead of "null" when there are no licenses.
if licenses == nil {
licenses = make([]codersdk.License, 0)
}

formatter := cliutil.NewLicenseFormatter(cliutil.LicenseFormatterOpts{
Sanitize: true,
})
out, err := formatter.Format(ctx, licenses)
if err != nil {
log.Error(ctx, "format licenses", slog.Error(err))
}
return out
}

func connectedAgentInfo(ctx context.Context, client *codersdk.Client, log slog.Logger, agentID uuid.UUID, eg *errgroup.Group, a *Agent) (closer func()) {
conn, err := workspacesdk.New(client).
DialAgent(ctx, agentID, &workspacesdk.DialAgentOptions{
Expand Down Expand Up @@ -534,11 +526,6 @@ func Run(ctx context.Context, d *Deps) (*Bundle, error) {
b.Agent = ai
return nil
})
eg.Go(func() error {
ls := LicenseStatus(ctx, d.Client, d.Log)
b.LicenseStatus = ls
return nil
})

_ = eg.Wait()

Expand Down
2 changes: 1 addition & 1 deletion support/support_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func TestRun(t *testing.T) {
assertSanitizedDeploymentConfig(t, bun.Deployment.Config)
assertNotNilNotEmpty(t, bun.Deployment.HealthReport, "deployment health report should be present")
assertNotNilNotEmpty(t, bun.Deployment.Experiments, "deployment experiments should be present")
require.NotNil(t, bun.Deployment.Licenses, "license status should be present")
assertNotNilNotEmpty(t, bun.Network.ConnectionInfo, "agent connection info should be present")
assertNotNilNotEmpty(t, bun.Network.CoordinatorDebug, "network coordinator debug should be present")
assertNotNilNotEmpty(t, bun.Network.Netcheck, "network netcheck should be present")
Expand All @@ -87,7 +88,6 @@ func TestRun(t *testing.T) {
assertNotNilNotEmpty(t, bun.Agent.Prometheus, "agent prometheus metrics should be present")
assertNotNilNotEmpty(t, bun.Agent.StartupLogs, "agent startup logs should be present")
assertNotNilNotEmpty(t, bun.Logs, "bundle logs should be present")
assertNotNilNotEmpty(t, bun.LicenseStatus, "license status should be present")
})

t.Run("OK_NoWorkspace", func(t *testing.T) {
Expand Down
Loading