package cli import ( "context" "encoding/json" "fmt" "time" "golang.org/x/xerrors" "github.com/coder/coder/v2/coderd/healthcheck/derphealth" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/healthsdk" "github.com/coder/coder/v2/codersdk/workspacesdk" "github.com/coder/serpent" ) func (r *RootCmd) netcheck() *serpent.Command { client := new(codersdk.Client) cmd := &serpent.Command{ Use: "netcheck", Short: "Print network debug information for DERP and STUN", Middleware: serpent.Chain( r.InitClient(client), ), Handler: func(inv *serpent.Invocation) error { ctx, cancel := context.WithTimeout(inv.Context(), 30*time.Second) defer cancel() connInfo, err := workspacesdk.New(client).AgentConnectionInfoGeneric(ctx) if err != nil { return err } _, _ = fmt.Fprint(inv.Stderr, "Gathering a network report. This may take a few seconds...\n\n") var derpReport derphealth.Report derpReport.Run(ctx, &derphealth.ReportOptions{ DERPMap: connInfo.DERPMap, }) ifReport, err := healthsdk.RunInterfacesReport() if err != nil { return xerrors.Errorf("failed to run interfaces report: %w", err) } report := healthsdk.ClientNetcheckReport{ DERP: healthsdk.DERPHealthReport(derpReport), Interfaces: ifReport, } raw, err := json.MarshalIndent(report, "", " ") if err != nil { return err } n, err := inv.Stdout.Write(raw) if err != nil { return err } if n != len(raw) { return xerrors.Errorf("failed to write all bytes to stdout; wrote %d, len %d", n, len(raw)) } _, _ = inv.Stdout.Write([]byte("\n")) return nil }, } cmd.Options = serpent.OptionSet{} return cmd }