@@ -79,14 +79,15 @@ func DefaultWorkspaceProvider(ctx context.Context, c coder.Client) (*coder.Kuber
7979// WorkspaceTable defines an Workspace-like structure with associated entities composed in a human
8080// readable form.
8181type WorkspaceTable struct {
82- Name string `table:"Name"`
83- Image string `table:"Image"`
84- CPU float32 `table:"vCPU"`
85- MemoryGB float32 `table:"MemoryGB"`
86- DiskGB int `table:"DiskGB"`
87- Status string `table:"Status"`
88- Provider string `table:"Provider"`
89- CVM bool `table:"CVM"`
82+ Name string `table:"Name" json:"name"`
83+ Image string `table:"Image" json:"image"`
84+ CPU float32 `table:"vCPU" json:"cpu"`
85+ MemoryGB float32 `table:"MemoryGB" json:"memory_gb"`
86+ DiskGB int `table:"DiskGB" json:"disk_gb"`
87+ Status string `table:"Status" json:"status"`
88+ Provider string `table:"Provider" json:"provider"`
89+ CVM bool `table:"CVM" json:"cvm"`
90+ Username string `table:"Username" json:"username"`
9091}
9192
9293// WorkspacesHumanTable performs the composition of each Workspace with its associated ProviderName and ImageRepo.
@@ -96,6 +97,11 @@ func WorkspacesHumanTable(ctx context.Context, client coder.Client, workspaces [
9697 return nil , err
9798 }
9899
100+ userMap , err := MakeUserMap (ctx , client , workspaces )
101+ if err != nil {
102+ return nil , err
103+ }
104+
99105 pooledWorkspaces := make ([]WorkspaceTable , 0 , len (workspaces ))
100106 providers , err := client .WorkspaceProviders (ctx )
101107 if err != nil {
@@ -105,25 +111,66 @@ func WorkspacesHumanTable(ctx context.Context, client coder.Client, workspaces [
105111 for _ , p := range providers .Kubernetes {
106112 providerMap [p .ID ] = p
107113 }
108- for _ , e := range workspaces {
109- workspaceProvider , ok := providerMap [e .ResourcePoolID ]
114+ for _ , ws := range workspaces {
115+ workspaceProvider , ok := providerMap [ws .ResourcePoolID ]
110116 if ! ok {
111117 return nil , xerrors .Errorf ("fetch workspace workspace provider: %w" , coder .ErrNotFound )
112118 }
113119 pooledWorkspaces = append (pooledWorkspaces , WorkspaceTable {
114- Name : e .Name ,
115- Image : fmt .Sprintf ("%s:%s" , imageMap [e .ImageID ].Repository , e .ImageTag ),
116- CPU : e .CPUCores ,
117- MemoryGB : e .MemoryGB ,
118- DiskGB : e .DiskGB ,
119- Status : string (e .LatestStat .ContainerStatus ),
120+ Name : ws .Name ,
121+ Image : fmt .Sprintf ("%s:%s" , imageMap [ws .ImageID ].Repository , ws .ImageTag ),
122+ CPU : ws .CPUCores ,
123+ MemoryGB : ws .MemoryGB ,
124+ DiskGB : ws .DiskGB ,
125+ Status : string (ws .LatestStat .ContainerStatus ),
120126 Provider : workspaceProvider .Name ,
121- CVM : e .UseContainerVM ,
127+ CVM : ws .UseContainerVM ,
128+ Username : userMap [ws .UserID ].Username ,
122129 })
123130 }
124131 return pooledWorkspaces , nil
125132}
126133
134+ func MakeUserMap (ctx context.Context , client coder.Client , workspaces []coder.Workspace ) (map [string ]* coder.User , error ) {
135+ var (
136+ mu sync.Mutex
137+ egroup = clog .LoggedErrGroup ()
138+ )
139+
140+ userMap := map [string ]* coder.User {}
141+
142+ // Iterate over all the workspaces to get a list of unique User IDs.
143+ for _ , ws := range workspaces {
144+ userMap [ws .UserID ] = nil
145+ }
146+
147+ fetchIds := make ([]string , 0 , len (userMap ))
148+ for id := range userMap {
149+ fetchIds = append (fetchIds , id )
150+ }
151+
152+ for _ , id := range fetchIds {
153+ id := id
154+ egroup .Go (func () error {
155+ user , err := client .UserByID (ctx , id )
156+ if err != nil {
157+ return xerrors .Errorf ("get user by id: %w" , err )
158+ }
159+ mu .Lock ()
160+ defer mu .Unlock ()
161+
162+ userMap [id ] = user
163+ return nil
164+ })
165+ }
166+
167+ if err := egroup .Wait (); err != nil {
168+ return nil , xerrors .Errorf ("fetch all workspace users: %w" , err )
169+ }
170+
171+ return userMap , nil
172+ }
173+
127174// MakeImageMap fetches all image entities specified in the slice of workspaces, then places them into an ID map.
128175func MakeImageMap (ctx context.Context , client coder.Client , workspaces []coder.Workspace ) (map [string ]* coder.Image , error ) {
129176 var (
0 commit comments