Skip to content

Commit 3c95386

Browse files
authored
fix: Update workspace structure to fix inference deploy command (#35)
Fix workspace structure Signed-off-by: Heba Elayoty <[email protected]>
1 parent b81de74 commit 3c95386

File tree

2 files changed

+241
-128
lines changed

2 files changed

+241
-128
lines changed

pkg/deploy.go

Lines changed: 110 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -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
291310
func (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

476496
func createInferenceConfigMap(clientset kubernetes.Interface, configFile, workspaceName, namespace string) error {

0 commit comments

Comments
 (0)