Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit28e09c5

Browse files
committed
feat(cli): improve devcontainer support forcoder show
Fixescoder/internal#747
1 parent211393a commit28e09c5

13 files changed

+586
-29
lines changed

‎cli/cliui/resources.go

Lines changed: 127 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"golang.org/x/mod/semver"
1313

1414
"github.com/coder/coder/v2/coderd/database/dbtime"
15+
"github.com/coder/coder/v2/coderd/util/slice"
1516
"github.com/coder/coder/v2/codersdk"
1617
"github.com/coder/pretty"
1718
)
@@ -29,6 +30,7 @@ type WorkspaceResourcesOptions struct {
2930
ServerVersionstring
3031
ListeningPortsmap[uuid.UUID]codersdk.WorkspaceAgentListeningPortsResponse
3132
Devcontainersmap[uuid.UUID]codersdk.WorkspaceAgentListContainersResponse
33+
ShowDetailsbool
3234
}
3335

3436
// WorkspaceResources displays the connection status and tree-view of provided resources.
@@ -69,7 +71,11 @@ func WorkspaceResources(writer io.Writer, resources []codersdk.WorkspaceResource
6971

7072
totalAgents:=0
7173
for_,resource:=rangeresources {
72-
totalAgents+=len(resource.Agents)
74+
for_,agent:=rangeresource.Agents {
75+
if!agent.ParentID.Valid {
76+
totalAgents++
77+
}
78+
}
7379
}
7480

7581
for_,resource:=rangeresources {
@@ -94,12 +100,15 @@ func WorkspaceResources(writer io.Writer, resources []codersdk.WorkspaceResource
94100
"",
95101
})
96102
// Display all agents associated with the resource.
97-
forindex,agent:=rangeresource.Agents {
103+
agents:=slice.Filter(resource.Agents,func(agent codersdk.WorkspaceAgent)bool {
104+
return!agent.ParentID.Valid
105+
})
106+
forindex,agent:=rangeagents {
98107
tableWriter.AppendRow(renderAgentRow(agent,index,totalAgents,options))
99108
for_,row:=rangerenderListeningPorts(options,agent.ID,index,totalAgents) {
100109
tableWriter.AppendRow(row)
101110
}
102-
for_,row:=rangerenderDevcontainers(options,agent.ID,index,totalAgents) {
111+
for_,row:=rangerenderDevcontainers(resources,options,agent.ID,index,totalAgents) {
103112
tableWriter.AppendRow(row)
104113
}
105114
}
@@ -125,7 +134,7 @@ func renderAgentRow(agent codersdk.WorkspaceAgent, index, totalAgents int, optio
125134
}
126135
if!options.HideAccess {
127136
sshCommand:="coder ssh "+options.WorkspaceName
128-
iftotalAgents>1 {
137+
iftotalAgents>1||len(options.Devcontainers)>0{
129138
sshCommand+="."+agent.Name
130139
}
131140
sshCommand=pretty.Sprint(DefaultStyles.Code,sshCommand)
@@ -164,45 +173,135 @@ func renderPortRow(port codersdk.WorkspaceAgentListeningPort, idx, total int) ta
164173
return table.Row{sb.String()}
165174
}
166175

167-
funcrenderDevcontainers(wroWorkspaceResourcesOptions,agentID uuid.UUID,index,totalAgentsint) []table.Row {
176+
funcrenderDevcontainers(resources []codersdk.WorkspaceResource,wroWorkspaceResourcesOptions,agentID uuid.UUID,index,totalAgentsint) []table.Row {
168177
varrows []table.Row
169178
ifwro.Devcontainers==nil {
170179
return []table.Row{}
171180
}
172181
dc,ok:=wro.Devcontainers[agentID]
173-
if!ok||len(dc.Containers)==0 {
182+
if!ok||len(dc.Devcontainers)==0 {
174183
return []table.Row{}
175184
}
176185
rows=append(rows, table.Row{
177186
fmt.Sprintf(" %s─ %s",renderPipe(index,totalAgents),"Devcontainers"),
178187
})
179-
foridx,container:=rangedc.Containers {
180-
rows=append(rows,renderDevcontainerRow(container,idx,len(dc.Containers)))
188+
foridx,devcontainer:=rangedc.Devcontainers {
189+
rows=append(rows,renderDevcontainerRow(resources,devcontainer,idx,len(dc.Devcontainers),wro)...)
181190
}
182191
returnrows
183192
}
184193

185-
funcrenderDevcontainerRow(container codersdk.WorkspaceAgentContainer,index,totalint) table.Row {
186-
varrow table.Row
187-
varsb strings.Builder
188-
_,_=sb.WriteString(" ")
189-
_,_=sb.WriteString(renderPipe(index,total))
190-
_,_=sb.WriteString("─ ")
191-
_,_=sb.WriteString(pretty.Sprintf(DefaultStyles.Code,"%s",container.FriendlyName))
192-
row=append(row,sb.String())
193-
sb.Reset()
194-
ifcontainer.Running {
195-
_,_=sb.WriteString(pretty.Sprintf(DefaultStyles.Keyword,"(%s)",container.Status))
196-
}else {
197-
_,_=sb.WriteString(pretty.Sprintf(DefaultStyles.Error,"(%s)",container.Status))
194+
funcrenderDevcontainerRow(resources []codersdk.WorkspaceResource,devcontainer codersdk.WorkspaceAgentDevcontainer,index,totalint,wroWorkspaceResourcesOptions) []table.Row {
195+
varrows []table.Row
196+
197+
// If the devcontainer is running and has an associated agent, we want to
198+
// display the agent's details. Otherwise, we just display the devcontainer
199+
// name and status.
200+
varsubAgent*codersdk.WorkspaceAgent
201+
displayName:=devcontainer.Name
202+
ifdevcontainer.Agent!=nil&&devcontainer.Status==codersdk.WorkspaceAgentDevcontainerStatusRunning {
203+
for_,resource:=rangeresources {
204+
for_,agent:=rangeresource.Agents {
205+
ifagent.ID==devcontainer.Agent.ID {
206+
subAgent=&agent
207+
break
208+
}
209+
}
210+
ifsubAgent!=nil {
211+
break
212+
}
213+
}
214+
215+
displayName=devcontainer.Agent.Name
216+
ifsubAgent!=nil {
217+
displayName+=fmt.Sprintf(" (%s, %s)",subAgent.OperatingSystem,subAgent.Architecture)
218+
}else {
219+
displayName+=" (linux, amd64)"
220+
}
221+
}
222+
223+
ifdevcontainer.Container!=nil {
224+
displayName+=" "+pretty.Sprint(DefaultStyles.Keyword,"["+devcontainer.Container.FriendlyName+"]")
225+
}
226+
227+
// Build the main row.
228+
row:= table.Row{
229+
fmt.Sprintf(" %s─ %s",renderPipe(index,total),displayName),
230+
}
231+
232+
// Add status, health, and version columns.
233+
if!wro.HideAgentState {
234+
ifsubAgent!=nil {
235+
row=append(row,renderAgentStatus(*subAgent))
236+
row=append(row,renderAgentHealth(*subAgent))
237+
row=append(row,renderAgentVersion(subAgent.Version,wro.ServerVersion))
238+
}else {
239+
row=append(row,renderDevcontainerStatus(devcontainer.Status))
240+
row=append(row,"")// No health for devcontainer without agent.
241+
row=append(row,"")// No version for devcontainer without agent.
242+
}
243+
}
244+
245+
// Add access column.
246+
if!wro.HideAccess {
247+
ifsubAgent!=nil {
248+
accessString:=fmt.Sprintf("coder ssh %s.%s",wro.WorkspaceName,subAgent.Name)
249+
row=append(row,pretty.Sprint(DefaultStyles.Code,accessString))
250+
}else {
251+
row=append(row,"")// No access for devcontainers without agent.
252+
}
253+
}
254+
255+
rows=append(rows,row)
256+
257+
// Add error message if present.
258+
iferrorMessage:=devcontainer.Error;errorMessage!="" {
259+
// Cap error message length for display.
260+
if!wro.ShowDetails&&len(errorMessage)>80 {
261+
errorMessage=errorMessage[:77]+"..."
262+
}
263+
errorRow:= table.Row{
264+
" × "+pretty.Sprint(DefaultStyles.Error,errorMessage),
265+
"",
266+
"",
267+
"",
268+
}
269+
if!wro.HideAccess {
270+
errorRow=append(errorRow,"")
271+
}
272+
rows=append(rows,errorRow)
273+
}
274+
275+
// Add listening ports for the devcontainer agent.
276+
ifsubAgent!=nil {
277+
portRows:=renderListeningPorts(wro,subAgent.ID,index,total)
278+
for_,portRow:=rangeportRows {
279+
// Adjust indentation for ports under devcontainer agent.
280+
iflen(portRow)>0 {
281+
ifstr,ok:=portRow[0].(string);ok {
282+
portRow[0]=" "+str[3:]// Add extra indentation.
283+
}
284+
}
285+
rows=append(rows,portRow)
286+
}
287+
}
288+
289+
returnrows
290+
}
291+
292+
funcrenderDevcontainerStatus(status codersdk.WorkspaceAgentDevcontainerStatus)string {
293+
switchstatus {
294+
casecodersdk.WorkspaceAgentDevcontainerStatusRunning:
295+
returnpretty.Sprint(DefaultStyles.Keyword,"▶ running")
296+
casecodersdk.WorkspaceAgentDevcontainerStatusStopped:
297+
returnpretty.Sprint(DefaultStyles.Placeholder,"⏹ stopped")
298+
casecodersdk.WorkspaceAgentDevcontainerStatusStarting:
299+
returnpretty.Sprint(DefaultStyles.Warn,"⧗ starting")
300+
casecodersdk.WorkspaceAgentDevcontainerStatusError:
301+
returnpretty.Sprint(DefaultStyles.Error,"✘ error")
302+
default:
303+
returnpretty.Sprint(DefaultStyles.Placeholder,"○ "+string(status))
198304
}
199-
row=append(row,sb.String())
200-
sb.Reset()
201-
// "health" is not applicable here.
202-
row=append(row,sb.String())
203-
_,_=sb.WriteString(container.Image)
204-
row=append(row,sb.String())
205-
returnrow
206305
}
207306

208307
funcrenderAgentStatus(agent codersdk.WorkspaceAgent)string {

‎cli/show.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,17 @@ import (
1515

1616
func (r*RootCmd)show()*serpent.Command {
1717
client:=new(codersdk.Client)
18+
vardetailsbool
1819
return&serpent.Command{
1920
Use:"show <workspace>",
2021
Short:"Display details of a workspace's resources and agents",
22+
Options: serpent.OptionSet{
23+
{
24+
Flag:"details",
25+
Description:"Show full error messages and additional details.",
26+
Value:serpent.BoolOf(&details),
27+
},
28+
},
2129
Middleware:serpent.Chain(
2230
serpent.RequireNArgs(1),
2331
r.InitClient(client),
@@ -35,13 +43,15 @@ func (r *RootCmd) show() *serpent.Command {
3543
options:= cliui.WorkspaceResourcesOptions{
3644
WorkspaceName:workspace.Name,
3745
ServerVersion:buildInfo.Version,
46+
ShowDetails:details,
3847
}
3948
ifworkspace.LatestBuild.Status==codersdk.WorkspaceStatusRunning {
4049
// Get listening ports for each agent.
4150
ports,devcontainers:=fetchRuntimeResources(inv,client,workspace.LatestBuild.Resources...)
4251
options.ListeningPorts=ports
4352
options.Devcontainers=devcontainers
4453
}
54+
4555
returncliui.WorkspaceResources(inv.Stdout,workspace.LatestBuild.Resources,options)
4656
},
4757
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp