@@ -17,6 +17,7 @@ limitations under the License.
1717package  api
1818
1919import  (
20+ 	"bytes" 
2021	"encoding/json" 
2122	"fmt" 
2223	"io" 
@@ -254,4 +255,124 @@ var _ = Describe("WorkspaceKinds Handler", func() {
254255			Expect (rs .StatusCode ).To (Equal (http .StatusNotFound ), descUnexpectedHTTPStatus , rr .Body .String ())
255256		})
256257	})
258+ 
259+ 	// NOTE: these tests create and delete resources on the cluster, so cannot be run in parallel. 
260+ 	//       therefore, we run them using the `Serial` Ginkgo decorator. 
261+ 	Context ("when creating a WorkspaceKind" , Serial , func () {
262+ 
263+ 		var  newWorkspaceKindName  =  "wsk-create-test" 
264+ 
265+ 		AfterEach (func () {
266+ 			By ("cleaning up the created WorkspaceKind" )
267+ 			wsk  :=  & kubefloworgv1beta1.WorkspaceKind {
268+ 				ObjectMeta : metav1.ObjectMeta {
269+ 					Name : newWorkspaceKindName ,
270+ 				},
271+ 			}
272+ 			_  =  k8sClient .Delete (ctx , wsk )
273+ 		})
274+ 
275+ 		It ("should succeed when creating a new WorkspaceKind with valid YAML" , func () {
276+ 			By ("defining the final, complete, and valid YAML payload" )
277+ 			// This YAML now includes the icon and logo fields required by the API server. 
278+ 			validYAML  :=  []byte (fmt .Sprintf (` 
279+ apiVersion: workspaces.kubeflow.org/v1beta1 
280+ kind: WorkspaceKind 
281+ metadata: 
282+   name: %s 
283+ spec: 
284+   spawner: 
285+     displayName: "Test Jupyter Environment" 
286+     description: "A valid description for testing." 
287+     icon: 
288+       url: "https://example.com/icon.png" 
289+     logo: 
290+       url: "https://example.com/logo.svg" 
291+   podTemplate: 
292+     options: 
293+       imageConfig: 
294+         spawner: 
295+           default: "default-image" 
296+         values: 
297+         - id: "default-image" 
298+           name: "Jupyter Scipy" 
299+           path: "kubeflownotebooks/jupyter-scipy:v1.9.0" 
300+           spawner: 
301+             displayName: "Jupyter with SciPy v1.9.0" 
302+           spec: 
303+             image: "kubeflownotebooks/jupyter-scipy:v1.9.0" 
304+             ports: 
305+             - id: "notebook-port" 
306+               displayName: "Notebook Port" 
307+               port: 8888 
308+               protocol: "HTTP" 
309+       podConfig: 
310+         spawner: 
311+           default: "default-pod-config" 
312+         values: 
313+         - id: "default-pod-config" 
314+           name: "Default Resources" 
315+           spawner: 
316+             displayName: "Small CPU/RAM" 
317+           resources: 
318+             requests: 
319+               cpu: "500m" 
320+               memory: "1Gi" 
321+             limits: 
322+               cpu: "1" 
323+               memory: "2Gi" 
324+     volumeMounts: 
325+       home: "/home/jovyan" 
326+ ` , newWorkspaceKindName ))
327+ 
328+ 			By ("creating the HTTP request" )
329+ 			req , err  :=  http .NewRequest (http .MethodPost , AllWorkspaceKindsPath , bytes .NewReader (validYAML ))
330+ 			Expect (err ).NotTo (HaveOccurred ())
331+ 			req .Header .Set ("Content-Type" , "application/vnd.kubeflow-notebooks.manifest+yaml" )
332+ 			req .Header .Set (userIdHeader , adminUser )
333+ 
334+ 			By ("executing the CreateWorkspaceKindHandler" )
335+ 			rr  :=  httptest .NewRecorder ()
336+ 			a .CreateWorkspaceKindHandler (rr , req , httprouter.Params {})
337+ 			rs  :=  rr .Result ()
338+ 			defer  rs .Body .Close ()
339+ 
340+ 			By ("verifying the HTTP response status code is 201 Created" )
341+ 			Expect (rs .StatusCode ).To (Equal (http .StatusCreated ), "Body: %s" , rr .Body .String ())
342+ 
343+ 			By ("verifying the resource was created in the cluster" )
344+ 			createdWsk  :=  & kubefloworgv1beta1.WorkspaceKind {}
345+ 			err  =  k8sClient .Get (ctx , types.NamespacedName {Name : newWorkspaceKindName }, createdWsk )
346+ 			Expect (err ).NotTo (HaveOccurred ())
347+ 		})
348+ 		It ("should fail if the YAML is syntactically invalid" , func () {
349+ 			By ("defining a string that is not valid YAML" )
350+ 			// This text has incorrect indentation and structure. 
351+ 			invalidYAML  :=  []byte (` 
352+ apiVersion: v1 
353+ kind: WorkspaceKind 
354+ metadata 
355+   name: broken-yaml 
356+ ` )
357+ 
358+ 			By ("creating the HTTP request" )
359+ 			req , err  :=  http .NewRequest (http .MethodPost , AllWorkspaceKindsPath , bytes .NewReader (invalidYAML ))
360+ 			Expect (err ).NotTo (HaveOccurred ())
361+ 			req .Header .Set ("Content-Type" , "application/vnd.kubeflow-notebooks.manifest+yaml" )
362+ 			req .Header .Set (userIdHeader , adminUser )
363+ 
364+ 			By ("executing the CreateWorkspaceKindHandler" )
365+ 			rr  :=  httptest .NewRecorder ()
366+ 			a .CreateWorkspaceKindHandler (rr , req , httprouter.Params {})
367+ 			rs  :=  rr .Result ()
368+ 			defer  rs .Body .Close ()
369+ 
370+ 			By ("verifying the handler returns a 400 Bad Request with a valid error envelope" )
371+ 			Expect (rs .StatusCode ).To (Equal (http .StatusBadRequest ))
372+ 			var  response  ErrorEnvelope 
373+ 			err  =  json .Unmarshal (rr .Body .Bytes (), & response )
374+ 			Expect (err ).NotTo (HaveOccurred (), "The error response should be valid JSON" )
375+ 			Expect (response .Error .Message ).To (ContainSubstring ("failed to parse YAML manifest" ))
376+ 		})
377+ 	})
257378})
0 commit comments