@@ -257,6 +257,24 @@ func (o *DeployOptions) Run() error {
257257 return fmt .Errorf ("failed to create dynamic client: %w" , err )
258258 }
259259
260+ // Create Kubernetes client
261+ clientset , err := kubernetes .NewForConfig (config )
262+ if err != nil {
263+ klog .Errorf ("Failed to create Kubernetes client: %v" , err )
264+ return fmt .Errorf ("failed to create Kubernetes client: %w" , err )
265+ }
266+
267+ // Create ConfigMap if inference config is a file path
268+ if ! o .Tuning && o .InferenceConfig != "" {
269+ // Check if it's a file path
270+ if _ , statErr := os .Stat (o .InferenceConfig ); statErr == nil {
271+ if createErr := createInferenceConfigMap (clientset , o .InferenceConfig , o .WorkspaceName , o .Namespace ); createErr != nil {
272+ klog .Errorf ("Failed to create inference ConfigMap: %v" , createErr )
273+ return fmt .Errorf ("failed to create inference ConfigMap: %w" , createErr )
274+ }
275+ }
276+ }
277+
260278 // Create workspace
261279 workspace := o .buildWorkspace ()
262280
@@ -288,118 +306,108 @@ func (o *DeployOptions) Run() error {
288306 return nil
289307}
290308
309+ // buildWorkspace creates a new Workspace object with the specified configuration
291310func (o * DeployOptions ) buildWorkspace () * unstructured.Unstructured {
292311 klog .V (4 ).Info ("Building workspace configuration" )
293312
294- // Create the base workspace object
295- workspace := & unstructured.Unstructured {
296- Object : map [string ]interface {}{
297- "apiVersion" : "kaito.sh/v1beta1" ,
298- "kind" : "Workspace" ,
299- "metadata" : map [string ]interface {}{
300- "name" : o .WorkspaceName ,
301- "namespace" : o .Namespace ,
302- },
303- },
313+ // Create and initialize the workspace object
314+ workspace := o .initWorkspaceObject ()
315+
316+ // Set resource configuration
317+ o .setResourceConfig (workspace )
318+
319+ // Configure inference or tuning
320+ if o .Tuning {
321+ o .setTuningConfig (workspace )
322+ } else {
323+ o .setInferenceConfig (workspace )
304324 }
305325
306326 // Add LoadBalancer annotation if requested
307327 if o .EnableLoadBalancer {
308- metadata := workspace .Object ["metadata" ].(map [string ]interface {})
309- if metadata ["annotations" ] == nil {
310- metadata ["annotations" ] = map [string ]interface {}{}
311- }
312- annotations := metadata ["annotations" ].(map [string ]interface {})
313- annotations ["kaito.sh/enable-lb" ] = "true"
314- klog .V (4 ).Info ("Added LoadBalancer annotation to workspace" )
328+ o .setLoadBalancerAnnotation (workspace )
315329 }
316330
317- // Add the spec fields under the spec field
318- workspace .Object ["spec" ] = o .createWorkspaceSpec ()
319-
320331 return workspace
321332}
322333
323- func (o * DeployOptions ) createWorkspaceSpec () map [string ]interface {} {
324- klog .V (4 ).Info ("Creating workspace specification" )
334+ // initWorkspaceObject creates and initializes a new Workspace object with basic metadata
335+ func (o * DeployOptions ) initWorkspaceObject () * unstructured.Unstructured {
336+ workspace := & unstructured.Unstructured {
337+ Object : make (map [string ]interface {}),
338+ }
339+
340+ workspace .SetAPIVersion ("kaito.sh/v1beta1" )
341+ workspace .SetKind ("Workspace" )
342+ workspace .SetName (o .WorkspaceName )
343+ workspace .SetNamespace (o .Namespace )
325344
326- spec := map [string ]interface {}{
327- "resource" : map [string ]interface {}{
328- "instanceType" : o .InstanceType ,
345+ return workspace
346+ }
347+
348+ // setResourceConfig sets the resource configuration at the root level
349+ func (o * DeployOptions ) setResourceConfig (workspace * unstructured.Unstructured ) {
350+ resource := map [string ]interface {}{
351+ "instanceType" : o .InstanceType ,
352+ "labelSelector" : map [string ]interface {}{
353+ "matchLabels" : map [string ]interface {}{
354+ "kaito.sh/workspace" : o .WorkspaceName ,
355+ },
329356 },
330357 }
331358
332- // Add node count if specified
333359 if o .Count > 0 {
334- spec ["resource" ].(map [string ]interface {})["count" ] = o .Count
335- klog .V (4 ).Infof ("Set node count to %d" , o .Count )
360+ resource ["count" ] = int64 (o .Count )
336361 }
337362
338- // Add label selector - use provided one or create a default
339- var labelSelector map [string ]interface {}
340363 if len (o .LabelSelector ) > 0 {
341- labelSelector = map [string ]interface {}{
342- "matchLabels" : o .LabelSelector ,
343- }
344- klog .V (4 ).Infof ("Added label selector: %v" , o .LabelSelector )
345- } else {
346- // Default label selector using workspace name
347- labelSelector = map [string ]interface {}{
348- "matchLabels" : map [string ]interface {}{
349- "kaito.sh/workspace" : o .WorkspaceName ,
350- },
351- }
352- klog .V (4 ).Infof ("Added default label selector for workspace: %s" , o .WorkspaceName )
364+ resource ["labelSelector" ].(map [string ]interface {})["matchLabels" ] = o .LabelSelector
353365 }
354- spec ["resource" ].(map [string ]interface {})["labelSelector" ] = labelSelector
355366
356- // Configure inference or tuning
357- if o .Tuning {
358- o .configureTuning (spec )
359- } else {
360- o .configureInference (spec )
367+ if err := unstructured .SetNestedField (workspace .Object , resource , "resource" ); err != nil {
368+ klog .Errorf ("Failed to set resource field: %v" , err )
361369 }
362-
363- return spec
364370}
365371
366- func (o * DeployOptions ) configureTuning (spec map [string ]interface {}) {
367- klog .V (3 ).Info ("Configuring tuning mode" )
368- // Tuning configuration
372+ // setTuningConfig sets the tuning configuration at the root level
373+ func (o * DeployOptions ) setTuningConfig (workspace * unstructured.Unstructured ) {
369374 tuning := map [string ]interface {}{}
370375
371376 if o .TuningMethod != "" {
372377 tuning ["method" ] = o .TuningMethod
373378 }
374379
380+ // Add model preset
375381 if o .Model != "" {
376382 preset := map [string ]interface {}{
377383 "name" : o .Model ,
378384 }
379385
380- // Add model image if specified
381386 if o .ModelImage != "" {
382- if preset ["presetOptions" ] == nil {
383- preset [ "presetOptions" ] = map [ string ] interface {}{}
387+ preset ["presetOptions" ] = map [ string ] interface {} {
388+ "image" : o . ModelImage ,
384389 }
385- presetOptions := preset ["presetOptions" ].(map [string ]interface {})
386- presetOptions ["image" ] = o .ModelImage
387- klog .V (4 ).Info ("Added custom model image" )
388390 }
389391
390392 tuning ["preset" ] = preset
391393 }
392394
395+ // Add input configuration
393396 if len (o .InputURLs ) > 0 {
397+ urls := make ([]interface {}, len (o .InputURLs ))
398+ for i , url := range o .InputURLs {
399+ urls [i ] = url
400+ }
394401 tuning ["input" ] = map [string ]interface {}{
395- "urls" : o . InputURLs ,
402+ "urls" : urls ,
396403 }
397404 } else if o .InputPVC != "" {
398405 tuning ["input" ] = map [string ]interface {}{
399406 "pvc" : o .InputPVC ,
400407 }
401408 }
402409
410+ // Add output configuration
403411 if o .OutputImage != "" {
404412 tuning ["output" ] = map [string ]interface {}{
405413 "image" : o .OutputImage ,
@@ -410,67 +418,79 @@ func (o *DeployOptions) configureTuning(spec map[string]interface{}) {
410418 }
411419 }
412420
421+ // Add output image secret if specified
413422 if o .OutputImageSecret != "" {
414423 if tuning ["output" ] == nil {
415424 tuning ["output" ] = map [string ]interface {}{}
416425 }
417426 tuning ["output" ].(map [string ]interface {})["imageSecret" ] = o .OutputImageSecret
418427 }
419428
429+ // Add tuning config if specified
420430 if o .TuningConfig != "" {
421431 tuning ["config" ] = o .TuningConfig
422432 }
423433
424- spec ["tuning" ] = tuning
434+ if err := unstructured .SetNestedField (workspace .Object , tuning , "tuning" ); err != nil {
435+ klog .Errorf ("Failed to set tuning field: %v" , err )
436+ }
425437}
426438
427- func (o * DeployOptions ) configureInference (spec map [string ]interface {}) {
428- klog .V (3 ).Info ("Configuring inference mode" )
429- // Inference configuration
439+ // setInferenceConfig sets the inference configuration at the root level
440+ func (o * DeployOptions ) setInferenceConfig (workspace * unstructured.Unstructured ) {
430441 inference := map [string ]interface {}{}
431442
443+ // Add model preset
432444 if o .Model != "" {
433- inference [ " preset" ] = map [string ]interface {}{
445+ preset : = map [string ]interface {}{
434446 "name" : o .Model ,
435447 }
436- }
437448
438- // Add model access secret if specified
439- if o .ModelAccessSecret != "" {
440- // Add modelAccessSecret under presetOptions
441- if inference ["preset" ] == nil {
442- inference ["preset" ] = map [string ]interface {}{
443- "name" : o .Model ,
444- "presetOptions" : map [string ]interface {}{
445- "modelAccessSecret" : o .ModelAccessSecret ,
446- },
447- }
448- } else {
449- preset := inference ["preset" ].(map [string ]interface {})
450- if preset ["presetOptions" ] == nil {
451- preset ["presetOptions" ] = map [string ]interface {}{}
449+ if o .ModelAccessSecret != "" {
450+ preset ["presetOptions" ] = map [string ]interface {}{
451+ "modelAccessSecret" : o .ModelAccessSecret ,
452452 }
453- presetOptions := preset ["presetOptions" ].(map [string ]interface {})
454- presetOptions ["modelAccessSecret" ] = o .ModelAccessSecret
455453 }
456- klog .V (4 ).Info ("Added private model access configuration" )
454+
455+ inference ["preset" ] = preset
457456 }
458457
459458 // Add adapters if specified
460459 if len (o .Adapters ) > 0 {
461- inference ["adapters" ] = o .Adapters
462- klog .V (4 ).Infof ("Added adapters: %v" , o .Adapters )
460+ adapters := make ([]interface {}, len (o .Adapters ))
461+ for i , adapter := range o .Adapters {
462+ adapters [i ] = adapter
463+ }
464+ inference ["adapters" ] = adapters
463465 }
464466
465467 // Add inference config if specified
466468 if o .InferenceConfig != "" {
467- // Create a ConfigMap name from the workspace name
468- configMapName := fmt .Sprintf ("%s-inference-config" , o .WorkspaceName )
469- inference ["config" ] = configMapName
470- klog .V (4 ).Info ("Added inference configuration" )
469+ // Check if it's a file path
470+ if _ , statErr := os .Stat (o .InferenceConfig ); statErr == nil {
471+ // Use the ConfigMap name that will be created
472+ configMapName := fmt .Sprintf ("%s-inference-config" , o .WorkspaceName )
473+ inference ["config" ] = configMapName
474+ } else {
475+ // Use the provided ConfigMap name directly
476+ inference ["config" ] = o .InferenceConfig
477+ }
478+ }
479+
480+ if err := unstructured .SetNestedField (workspace .Object , inference , "inference" ); err != nil {
481+ klog .Errorf ("Failed to set inference field: %v" , err )
471482 }
483+ }
472484
473- spec ["inference" ] = inference
485+ // setLoadBalancerAnnotation adds the LoadBalancer annotation to the workspace
486+ func (o * DeployOptions ) setLoadBalancerAnnotation (workspace * unstructured.Unstructured ) {
487+ metadata := workspace .Object ["metadata" ].(map [string ]interface {})
488+ if metadata ["annotations" ] == nil {
489+ metadata ["annotations" ] = map [string ]interface {}{}
490+ }
491+ annotations := metadata ["annotations" ].(map [string ]interface {})
492+ annotations ["kaito.sh/enable-lb" ] = "true"
493+ klog .V (4 ).Info ("Added LoadBalancer annotation to workspace" )
474494}
475495
476496func createInferenceConfigMap (clientset kubernetes.Interface , configFile , workspaceName , namespace string ) error {
0 commit comments