@@ -79,14 +79,15 @@ func DefaultWorkspaceProvider(ctx context.Context, c coder.Client) (*coder.Kuber
79
79
// WorkspaceTable defines an Workspace-like structure with associated entities composed in a human
80
80
// readable form.
81
81
type 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"`
90
91
}
91
92
92
93
// 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 [
96
97
return nil , err
97
98
}
98
99
100
+ userMap , err := MakeUserMap (ctx , client , workspaces )
101
+ if err != nil {
102
+ return nil , err
103
+ }
104
+
99
105
pooledWorkspaces := make ([]WorkspaceTable , 0 , len (workspaces ))
100
106
providers , err := client .WorkspaceProviders (ctx )
101
107
if err != nil {
@@ -105,25 +111,66 @@ func WorkspacesHumanTable(ctx context.Context, client coder.Client, workspaces [
105
111
for _ , p := range providers .Kubernetes {
106
112
providerMap [p .ID ] = p
107
113
}
108
- for _ , e := range workspaces {
109
- workspaceProvider , ok := providerMap [e .ResourcePoolID ]
114
+ for _ , ws := range workspaces {
115
+ workspaceProvider , ok := providerMap [ws .ResourcePoolID ]
110
116
if ! ok {
111
117
return nil , xerrors .Errorf ("fetch workspace workspace provider: %w" , coder .ErrNotFound )
112
118
}
113
119
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 ),
120
126
Provider : workspaceProvider .Name ,
121
- CVM : e .UseContainerVM ,
127
+ CVM : ws .UseContainerVM ,
128
+ Username : userMap [ws .UserID ].Username ,
122
129
})
123
130
}
124
131
return pooledWorkspaces , nil
125
132
}
126
133
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
+
127
174
// MakeImageMap fetches all image entities specified in the slice of workspaces, then places them into an ID map.
128
175
func MakeImageMap (ctx context.Context , client coder.Client , workspaces []coder.Workspace ) (map [string ]* coder.Image , error ) {
129
176
var (
0 commit comments