5
5
"io"
6
6
"sort"
7
7
"strconv"
8
+ "strings"
8
9
10
+ "github.com/google/uuid"
9
11
"github.com/jedib0t/go-pretty/v6/table"
10
12
"golang.org/x/mod/semver"
11
13
@@ -14,12 +16,18 @@ import (
14
16
"github.com/coder/pretty"
15
17
)
16
18
19
+ var (
20
+ pipeMid = "├"
21
+ pipeEnd = "└"
22
+ )
23
+
17
24
type WorkspaceResourcesOptions struct {
18
25
WorkspaceName string
19
26
HideAgentState bool
20
27
HideAccess bool
21
28
Title string
22
29
ServerVersion string
30
+ ListeningPorts map [uuid.UUID ]codersdk.WorkspaceAgentListeningPortsResponse
23
31
}
24
32
25
33
// WorkspaceResources displays the connection status and tree-view of provided resources.
@@ -86,39 +94,61 @@ func WorkspaceResources(writer io.Writer, resources []codersdk.WorkspaceResource
86
94
})
87
95
// Display all agents associated with the resource.
88
96
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
+ }
110
106
}
111
- sshCommand = pretty .Sprint (DefaultStyles .Code , sshCommand )
112
- row = append (row , sshCommand )
113
107
}
114
- tableWriter .AppendRow (row )
115
108
}
116
109
tableWriter .AppendSeparator ()
117
110
}
118
111
_ , err := fmt .Fprintln (writer , tableWriter .Render ())
119
112
return err
120
113
}
121
114
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
+
122
152
func renderAgentStatus (agent codersdk.WorkspaceAgent ) string {
123
153
switch agent .Status {
124
154
case codersdk .WorkspaceAgentConnecting :
@@ -163,3 +193,10 @@ func renderAgentVersion(agentVersion, serverVersion string) string {
163
193
}
164
194
return pretty .Sprint (DefaultStyles .Keyword , agentVersion )
165
195
}
196
+
197
+ func renderPipe (idx , total int ) string {
198
+ if idx == total - 1 {
199
+ return pipeEnd
200
+ }
201
+ return pipeMid
202
+ }
0 commit comments