@@ -19,6 +19,7 @@ package controller
19
19
import (
20
20
"context"
21
21
"fmt"
22
+ "github.com/kubeflow/notebooks/workspaces/controller/internal/istio"
22
23
"reflect"
23
24
"strings"
24
25
@@ -53,8 +54,6 @@ const (
53
54
workspaceSelectorLabel = "statefulset"
54
55
55
56
// lengths for resource names
56
- generateNameSuffixLength = 6
57
- maxServiceNameLength = 63
58
57
maxStatefulSetNameLength = 52 // https://github.com/kubernetes/kubernetes/issues/64023
59
58
60
59
// state message formats for Workspace status
@@ -342,10 +341,20 @@ func (r *WorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
342
341
}
343
342
}
344
343
345
- //
346
- // TODO: reconcile the Istio VirtualService to expose the Workspace
347
- // and implement the `spec.podTemplate.httpProxy` options
348
- //
344
+ // VirtualService reconciliation
345
+ virtualService , err := istio .GenerateIstioVirtualService (workspace , workspaceKind , currentImageConfig , serviceName , log )
346
+ if err != nil {
347
+ log .Error (err , "unable to generate Istio Virtual Service" )
348
+ }
349
+ log .Info (fmt .Sprintf ("VirtualService %s" , virtualService ))
350
+
351
+ if err := ctrl .SetControllerReference (workspace , virtualService , r .Scheme ); err != nil {
352
+ return ctrl.Result {}, err
353
+ }
354
+
355
+ if err := istio .ReconcileVirtualService (ctx , r .Client , virtualService .GetName (), virtualService .GetNamespace (), virtualService , log ); err != nil {
356
+ return ctrl.Result {}, err
357
+ }
349
358
350
359
// fetch Pod
351
360
// NOTE: the first StatefulSet Pod is always called "{statefulSetName}-0"
@@ -555,25 +564,10 @@ func getPodConfig(workspace *kubefloworgv1beta1.Workspace, workspaceKind *kubefl
555
564
}
556
565
}
557
566
558
- // generateNamePrefix generates a name prefix for a Workspace
559
- // the format is "ws-{WORKSPACE_NAME}-" the workspace name is truncated to fit within the max length
560
- func generateNamePrefix (workspaceName string , maxLength int ) string {
561
- namePrefix := fmt .Sprintf ("ws-%s" , workspaceName )
562
- maxLength = maxLength - generateNameSuffixLength // subtract 6 for the `metadata.generateName` suffix
563
- maxLength = maxLength - 1 // subtract 1 for the trailing "-"
564
- if len (namePrefix ) > maxLength {
565
- namePrefix = namePrefix [:min (len (namePrefix ), maxLength )]
566
- }
567
- if namePrefix [len (namePrefix )- 1 ] != '-' {
568
- namePrefix = namePrefix + "-"
569
- }
570
- return namePrefix
571
- }
572
-
573
567
// generateStatefulSet generates a StatefulSet for a Workspace
574
568
func generateStatefulSet (workspace * kubefloworgv1beta1.Workspace , workspaceKind * kubefloworgv1beta1.WorkspaceKind , imageConfigSpec kubefloworgv1beta1.ImageConfigSpec , podConfigSpec kubefloworgv1beta1.PodConfigSpec ) (* appsv1.StatefulSet , error ) {
575
569
// generate name prefix
576
- namePrefix := generateNamePrefix (workspace .Name , maxStatefulSetNameLength )
570
+ namePrefix := helper . GenerateNamePrefix (workspace .Name , maxStatefulSetNameLength )
577
571
578
572
// generate replica count
579
573
replicas := int32 (1 )
@@ -591,17 +585,7 @@ func generateStatefulSet(workspace *kubefloworgv1beta1.Workspace, workspaceKind
591
585
imagePullPolicy = * imageConfigSpec .ImagePullPolicy
592
586
}
593
587
594
- // define go string template functions
595
- // NOTE: these are used in places like the `extraEnv` values
596
588
containerPortsIdMap := make (map [string ]kubefloworgv1beta1.ImagePort )
597
- httpPathPrefixFunc := func (portId string ) string {
598
- port , ok := containerPortsIdMap [portId ]
599
- if ok {
600
- return fmt .Sprintf ("/workspace/%s/%s/%s/" , workspace .Namespace , workspace .Name , port .Id )
601
- } else {
602
- return ""
603
- }
604
- }
605
589
606
590
// generate container ports
607
591
containerPorts := make ([]corev1.ContainerPort , len (imageConfigSpec .Ports ))
@@ -620,14 +604,15 @@ func generateStatefulSet(workspace *kubefloworgv1beta1.Workspace, workspaceKind
620
604
// NOTE: we construct this map for use in the go string templates
621
605
containerPortsIdMap [port .Id ] = port
622
606
}
607
+ httpPathPrefixFunc := helper .GenerateHttpPathPrefixFunc (workspace , containerPortsIdMap )
623
608
624
609
// generate container env
625
610
containerEnv := make ([]corev1.EnvVar , len (workspaceKind .Spec .PodTemplate .ExtraEnv ))
626
611
for i , env := range workspaceKind .Spec .PodTemplate .ExtraEnv {
627
612
env := env .DeepCopy () // copy to avoid modifying the original
628
613
if env .Value != "" {
629
614
rawValue := env .Value
630
- outValue , err := helper .RenderExtraEnvValueTemplate (rawValue , httpPathPrefixFunc )
615
+ outValue , err := helper .RenderWithHttpPathPrefixFunc (rawValue , httpPathPrefixFunc )
631
616
if err != nil {
632
617
return nil , fmt .Errorf ("failed to render extraEnv %q: %w" , env .Name , err )
633
618
}
@@ -806,7 +791,7 @@ func generateStatefulSet(workspace *kubefloworgv1beta1.Workspace, workspaceKind
806
791
// generateService generates a Service for a Workspace
807
792
func generateService (workspace * kubefloworgv1beta1.Workspace , imageConfigSpec kubefloworgv1beta1.ImageConfigSpec ) (* corev1.Service , error ) {
808
793
// generate name prefix
809
- namePrefix := generateNamePrefix (workspace .Name , maxServiceNameLength )
794
+ namePrefix := helper . GenerateNamePrefix (workspace .Name , helper . MaxServiceNameLength )
810
795
811
796
// generate service ports
812
797
servicePorts := make ([]corev1.ServicePort , len (imageConfigSpec .Ports ))
0 commit comments