@@ -10,12 +10,13 @@ import (
10
10
"sort"
11
11
"strings"
12
12
13
- notebooksv1 "github.com/StatCan/jupyter-apis/notebooks/api /v1"
13
+ kubeflowv1 "github.com/StatCan/kubeflow-controller/pkg/apis/kubeflowcontroller /v1"
14
14
"github.com/andanhm/go-prettytime"
15
15
"github.com/gorilla/mux"
16
16
corev1 "k8s.io/api/core/v1"
17
17
"k8s.io/apimachinery/pkg/api/resource"
18
18
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
19
+ "k8s.io/apimachinery/pkg/labels"
19
20
)
20
21
21
22
const DefaultServiceAccountName string = "default-editor"
@@ -42,8 +43,8 @@ type volumerequest struct {
42
43
}
43
44
44
45
type gpurequest struct {
45
- Quantity resource. Quantity `json:"num"`
46
- Vendor string `json:"vendor"`
46
+ Quantity string `json:"num"`
47
+ Vendor string `json:"vendor"`
47
48
}
48
49
49
50
type newnotebookrequest struct {
@@ -105,21 +106,7 @@ const (
105
106
GPUVendorAMD GPUVendor = "amd"
106
107
)
107
108
108
- type EventsByTimestamp []corev1.Event
109
-
110
- func (e EventsByTimestamp ) Len () int {
111
- return len (e )
112
- }
113
-
114
- func (e EventsByTimestamp ) Less (a , b int ) bool {
115
- return e [b ].CreationTimestamp .Before (& e [a ].CreationTimestamp )
116
- }
117
-
118
- func (e EventsByTimestamp ) Swap (a , b int ) {
119
- e [a ], e [b ] = e [b ], e [a ]
120
- }
121
-
122
- func processStatus (notebook notebooksv1.Notebook , events []corev1.Event ) (Status , string ) {
109
+ func processStatus (notebook * kubeflowv1.Notebook , events []* corev1.Event ) (Status , string ) {
123
110
// Notebook is being deleted
124
111
if notebook .DeletionTimestamp != nil {
125
112
return StatusWaiting , "Deleting Notebook Server"
@@ -155,7 +142,7 @@ func processStatus(notebook notebooksv1.Notebook, events []corev1.Event) (Status
155
142
return "" , ""
156
143
}
157
144
158
- func processGPU (notebook notebooksv1 .Notebook ) (resource.Quantity , GPUVendor ) {
145
+ func processGPU (notebook * kubeflowv1 .Notebook ) (resource.Quantity , GPUVendor ) {
159
146
if limit , ok := notebook .Spec .Template .Spec .Containers [0 ].Resources .Limits ["nvidia.com/gpu" ]; ok {
160
147
return limit , GPUVendorNvidia
161
148
} else if limit , ok := notebook .Spec .Template .Spec .Containers [0 ].Resources .Limits ["amd.com/gpu" ]; ok {
@@ -171,36 +158,38 @@ func (s *server) GetNotebooks(w http.ResponseWriter, r *http.Request) {
171
158
172
159
log .Printf ("loading notebooks for %q" , namespace )
173
160
174
- notebooks , err := s .clientsets .notebooks .V1 (). Notebooks (namespace ).List (r . Context ())
161
+ notebooks , err := s .listers .notebooks .Notebooks (namespace ).List (labels . Everything ())
175
162
if err != nil {
176
163
s .error (w , r , err )
177
164
return
178
165
}
179
166
167
+ sort .Sort (notebooksByName (notebooks ))
168
+
180
169
resp := notebooksresponse {
181
170
APIResponse : APIResponse {
182
171
Success : true ,
183
172
},
184
173
Notebooks : make ([]notebookresponse , 0 ),
185
174
}
186
175
187
- for _ , notebook := range notebooks . Items {
176
+ for _ , notebook := range notebooks {
188
177
// Load events
189
- allevents , err := s .clientsets .kubernetes .CoreV1 ().Events (notebook .Namespace ).List (r .Context (), v1.ListOptions {
190
- FieldSelector : fmt .Sprintf ("involvedObject.kind=Notebook,involvedObject.name=%s" , notebook .Name ),
191
- })
178
+ allevents , err := s .listers .events .Events (notebook .Namespace ).List (labels .Everything ())
192
179
if err != nil {
193
180
log .Printf ("failed to load events for %s/%s: %v" , notebook .Namespace , notebook .Name , err )
194
181
}
195
182
196
183
// Filter past events
197
- events := make ([]corev1.Event , 0 )
198
- for _ , event := range allevents . Items {
199
- if ! event .CreationTimestamp .Before (& notebook .CreationTimestamp ) {
200
- events = append ( events , event )
184
+ events := make ([]* corev1.Event , 0 )
185
+ for _ , event := range allevents {
186
+ if event . InvolvedObject . Kind != "Notebook" || event . InvolvedObject . Name != notebook . Name || event .CreationTimestamp .Before (& notebook .CreationTimestamp ) {
187
+ continue
201
188
}
189
+
190
+ events = append (events , event )
202
191
}
203
- sort .Sort (EventsByTimestamp (events ))
192
+ sort .Sort (eventsByTimestamp (events ))
204
193
205
194
imageparts := strings .SplitAfter (notebook .Spec .Template .Spec .Containers [0 ].Image , "/" )
206
195
@@ -234,7 +223,7 @@ func (s *server) GetNotebooks(w http.ResponseWriter, r *http.Request) {
234
223
s .respond (w , r , resp )
235
224
}
236
225
237
- func (s * server ) handleVolume (ctx context.Context , req volumerequest , notebook * notebooksv1 .Notebook ) error {
226
+ func (s * server ) handleVolume (ctx context.Context , req volumerequest , notebook * kubeflowv1 .Notebook ) error {
238
227
if req .Type == VolumeTypeNew {
239
228
// Create the PVC
240
229
pvc := corev1.PersistentVolumeClaim {
@@ -308,13 +297,13 @@ func (s *server) NewNotebook(w http.ResponseWriter, r *http.Request) {
308
297
309
298
// Setup the notebook
310
299
// TODO: Work with default CPU/memory limits from config
311
- notebook := notebooksv1 .Notebook {
300
+ notebook := kubeflowv1 .Notebook {
312
301
ObjectMeta : v1.ObjectMeta {
313
302
Name : req .Name ,
314
303
Namespace : namespace ,
315
304
},
316
- Spec : notebooksv1 .NotebookSpec {
317
- Template : notebooksv1 .NotebookTemplateSpec {
305
+ Spec : kubeflowv1 .NotebookSpec {
306
+ Template : kubeflowv1 .NotebookTemplateSpec {
318
307
Spec : corev1.PodSpec {
319
308
ServiceAccountName : DefaultServiceAccountName ,
320
309
Containers : []corev1.Container {
@@ -374,15 +363,21 @@ func (s *server) NewNotebook(w http.ResponseWriter, r *http.Request) {
374
363
}
375
364
376
365
// Add GPU
377
- if ! req .GPUs .Quantity .IsZero () {
378
- notebook .Spec .Template .Spec .Containers [0 ].Resources .Requests [corev1 .ResourceName (req .GPUs .Vendor )] = req .GPUs .Quantity
379
- notebook .Spec .Template .Spec .Containers [0 ].Resources .Limits [corev1 .ResourceName (req .GPUs .Vendor )] = req .GPUs .Quantity
366
+ if req .GPUs .Quantity != "none" {
367
+ qty , err := resource .ParseQuantity (req .GPUs .Quantity )
368
+ if err != nil {
369
+ s .error (w , r , err )
370
+ return
371
+ }
372
+
373
+ notebook .Spec .Template .Spec .Containers [0 ].Resources .Requests [corev1 .ResourceName (req .GPUs .Vendor )] = qty
374
+ notebook .Spec .Template .Spec .Containers [0 ].Resources .Limits [corev1 .ResourceName (req .GPUs .Vendor )] = qty
380
375
}
381
376
382
377
log .Printf ("creating notebook %q for %q" , notebook .ObjectMeta .Name , namespace )
383
378
384
379
// Submit the notebook to the API server
385
- _ , err = s .clientsets .notebooks . V1 ().Notebooks (namespace ).Create (r .Context (), & notebook )
380
+ _ , err = s .clientsets .kubeflow . KubeflowV1 ().Notebooks (namespace ).Create (r .Context (), & notebook , v1. CreateOptions {} )
386
381
if err != nil {
387
382
s .error (w , r , err )
388
383
return
@@ -401,7 +396,7 @@ func (s *server) DeleteNotebook(w http.ResponseWriter, r *http.Request) {
401
396
log .Printf ("deleting notebook %q for %q" , notebook , namespace )
402
397
403
398
propagation := v1 .DeletePropagationForeground
404
- err := s .clientsets .notebooks . V1 ().Notebooks (namespace ).Delete (r .Context (), notebook , & v1.DeleteOptions {
399
+ err := s .clientsets .kubeflow . KubeflowV1 ().Notebooks (namespace ).Delete (r .Context (), notebook , v1.DeleteOptions {
405
400
PropagationPolicy : & propagation ,
406
401
})
407
402
if err != nil {
0 commit comments