55 "io"
66 "sort"
77 "strconv"
8+ "strings"
89
10+ "github.com/google/uuid"
911 "github.com/jedib0t/go-pretty/v6/table"
1012 "golang.org/x/mod/semver"
1113
@@ -14,12 +16,18 @@ import (
1416 "github.com/coder/pretty"
1517)
1618
19+ var (
20+ pipeMid = "├"
21+ pipeEnd = "└"
22+ )
23+
1724type WorkspaceResourcesOptions struct {
1825 WorkspaceName string
1926 HideAgentState bool
2027 HideAccess bool
2128 Title string
2229 ServerVersion string
30+ ListeningPorts map [uuid.UUID ]codersdk.WorkspaceAgentListeningPortsResponse
2331}
2432
2533// WorkspaceResources displays the connection status and tree-view of provided resources.
@@ -86,39 +94,61 @@ func WorkspaceResources(writer io.Writer, resources []codersdk.WorkspaceResource
8694 })
8795 // Display all agents associated with the resource.
8896 for index , agent := range resource .Agents {
89- pipe := "├"
90- if index == len (resource .Agents )- 1 {
91- pipe = "└"
92- }
93- row := table.Row {
94- // These tree from a resource!
95- fmt .Sprintf ("%s─ %s (%s, %s)" , pipe , agent .Name , agent .OperatingSystem , agent .Architecture ),
96- }
97- if ! options .HideAgentState {
98- var agentStatus , agentHealth , agentVersion string
99- if ! options .HideAgentState {
100- agentStatus = renderAgentStatus (agent )
101- agentHealth = renderAgentHealth (agent )
102- agentVersion = renderAgentVersion (agent .Version , options .ServerVersion )
103- }
104- row = append (row , agentStatus , agentHealth , agentVersion )
105- }
106- if ! options .HideAccess {
107- sshCommand := "coder ssh " + options .WorkspaceName
108- if totalAgents > 1 {
109- sshCommand += "." + agent .Name
97+ tableWriter .AppendRow (renderAgentRow (agent , index , totalAgents , options ))
98+ if options .ListeningPorts != nil {
99+ if lp , ok := options .ListeningPorts [agent .ID ]; ok && len (lp .Ports ) > 0 {
100+ tableWriter .AppendRow (table.Row {
101+ fmt .Sprintf (" %s─ %s" , renderPipe (index , totalAgents ), "Open Ports" ),
102+ })
103+ for _ , port := range lp .Ports {
104+ tableWriter .AppendRow (renderPortRow (port , index , totalAgents ))
105+ }
110106 }
111- sshCommand = pretty .Sprint (DefaultStyles .Code , sshCommand )
112- row = append (row , sshCommand )
113107 }
114- tableWriter .AppendRow (row )
115108 }
116109 tableWriter .AppendSeparator ()
117110 }
118111 _ , err := fmt .Fprintln (writer , tableWriter .Render ())
119112 return err
120113}
121114
115+ func renderAgentRow (agent codersdk.WorkspaceAgent , index , totalAgents int , options WorkspaceResourcesOptions ) table.Row {
116+ row := table.Row {
117+ // These tree from a resource!
118+ fmt .Sprintf ("%s─ %s (%s, %s)" , renderPipe (index , totalAgents ), agent .Name , agent .OperatingSystem , agent .Architecture ),
119+ }
120+ if ! options .HideAgentState {
121+ var agentStatus , agentHealth , agentVersion string
122+ if ! options .HideAgentState {
123+ agentStatus = renderAgentStatus (agent )
124+ agentHealth = renderAgentHealth (agent )
125+ agentVersion = renderAgentVersion (agent .Version , options .ServerVersion )
126+ }
127+ row = append (row , agentStatus , agentHealth , agentVersion )
128+ }
129+ if ! options .HideAccess {
130+ sshCommand := "coder ssh " + options .WorkspaceName
131+ if totalAgents > 1 {
132+ sshCommand += "." + agent .Name
133+ }
134+ sshCommand = pretty .Sprint (DefaultStyles .Code , sshCommand )
135+ row = append (row , sshCommand )
136+ }
137+ return row
138+ }
139+
140+ func renderPortRow (port codersdk.WorkspaceAgentListeningPort , index , totalPorts int ) table.Row {
141+ var sb strings.Builder
142+ _ , _ = sb .WriteString (" " )
143+ _ , _ = sb .WriteString (renderPipe (index , totalPorts ))
144+ _ , _ = sb .WriteString ("─ " )
145+ _ , _ = sb .WriteString (pretty .Sprintf (DefaultStyles .Code , "%5d/%s" , port .Port , port .Network ))
146+ if port .ProcessName != "" {
147+ _ , _ = sb .WriteString (pretty .Sprintf (DefaultStyles .Keyword , " [%s]" , port .ProcessName ))
148+ }
149+ return table.Row {sb .String ()}
150+ }
151+
122152func renderAgentStatus (agent codersdk.WorkspaceAgent ) string {
123153 switch agent .Status {
124154 case codersdk .WorkspaceAgentConnecting :
@@ -163,3 +193,10 @@ func renderAgentVersion(agentVersion, serverVersion string) string {
163193 }
164194 return pretty .Sprint (DefaultStyles .Keyword , agentVersion )
165195}
196+
197+ func renderPipe (idx , total int ) string {
198+ if idx == total - 1 {
199+ return pipeEnd
200+ }
201+ return pipeMid
202+ }
0 commit comments