@@ -30,6 +30,7 @@ import (
3030
3131const (
3232 workspaceIndex = "workspaceIndex"
33+ ipAddressIndex = "ipAddressIndex"
3334)
3435
3536// getPortStr extracts the port part from a given URL string. Returns "" if parsing fails or port is not specified.
@@ -77,6 +78,15 @@ func NewCRDWorkspaceInfoProvider(client client.Client, scheme *runtime.Scheme) (
7778
7879 return nil , xerrors .Errorf ("object is not a WorkspaceInfo" )
7980 },
81+ ipAddressIndex : func (obj interface {}) ([]string , error ) {
82+ if workspaceInfo , ok := obj .(* common.WorkspaceInfo ); ok {
83+ if workspaceInfo .IPAddress == "" {
84+ return nil , nil
85+ }
86+ return []string {workspaceInfo .IPAddress }, nil
87+ }
88+ return nil , xerrors .Errorf ("object is not a WorkspaceInfo" )
89+ },
8090 }
8191 contextIndexers := cache.Indexers {
8292 workspaceIndex : func (obj interface {}) ([]string , error ) {
@@ -96,29 +106,73 @@ func NewCRDWorkspaceInfoProvider(client client.Client, scheme *runtime.Scheme) (
96106 }, nil
97107}
98108
99- // WorkspaceInfo return the WorkspaceInfo available for the given workspaceID.
109+ // WorkspaceInfo returns the WorkspaceInfo for the given workspaceID.
110+ // It performs validation to ensure the workspace is unique and properly associated with its IP address.
100111func (r * CRDWorkspaceInfoProvider ) WorkspaceInfo (workspaceID string ) * common.WorkspaceInfo {
101112 workspaces , err := r .store .ByIndex (workspaceIndex , workspaceID )
102113 if err != nil {
103114 return nil
104115 }
105116
106- if len (workspaces ) >= 1 {
107- if len (workspaces ) != 1 {
108- log .Warnf ("multiple instances (%d) for workspace %s" , len (workspaces ), workspaceID )
109- }
117+ if len (workspaces ) == 0 {
118+ return nil
119+ }
110120
111- sort . Slice ( workspaces , func ( i , j int ) bool {
112- a := workspaces [ i ].( * common. WorkspaceInfo )
113- b := workspaces [ j ].( * common. WorkspaceInfo )
121+ if len ( workspaces ) > 1 {
122+ log . WithField ( "workspaceID" , workspaceID ). WithField ( "instanceCount" , len ( workspaces )). Warn ( "multiple workspace instances found" )
123+ }
114124
115- return a .StartedAt .After (b .StartedAt )
116- })
125+ sort .Slice (workspaces , func (i , j int ) bool {
126+ a := workspaces [i ].(* common.WorkspaceInfo )
127+ b := workspaces [j ].(* common.WorkspaceInfo )
128+ return a .StartedAt .After (b .StartedAt )
129+ })
130+
131+ wsInfo := workspaces [0 ].(* common.WorkspaceInfo )
132+
133+ if wsInfo .IPAddress == "" {
134+ return wsInfo
135+ }
136+
137+ if conflict , err := r .validateIPAddressConflict (workspaceID , wsInfo .IPAddress ); conflict || err != nil {
138+ return nil
139+ }
117140
118- return workspaces [0 ].(* common.WorkspaceInfo )
141+ return wsInfo
142+ }
143+
144+ func (r * CRDWorkspaceInfoProvider ) validateIPAddressConflict (workspaceID , ipAddress string ) (bool , error ) {
145+ wsInfos , err := r .workspacesInfoByIPAddress (ipAddress )
146+ if err != nil {
147+ log .WithError (err ).WithField ("workspaceID" , workspaceID ).WithField ("ipAddress" , ipAddress ).Error ("failed to get workspaces by IP address" )
148+ return true , err
149+ }
150+
151+ if len (wsInfos ) > 1 {
152+ log .WithField ("workspaceID" , workspaceID ).WithField ("ipAddress" , ipAddress ).WithField ("workspaceCount" , len (wsInfos )).Warn ("multiple workspaces found for IP address" )
153+ return true , nil
154+ }
155+
156+ if len (wsInfos ) == 1 && wsInfos [0 ].WorkspaceID != workspaceID {
157+ log .WithField ("workspaceID" , workspaceID ).WithField ("ipAddress" , ipAddress ).WithField ("foundWorkspaceID" , wsInfos [0 ].WorkspaceID ).Warn ("workspace IP address conflict detected" )
158+ return true , nil
159+ }
160+
161+ return false , nil
162+ }
163+
164+ func (r * CRDWorkspaceInfoProvider ) workspacesInfoByIPAddress (ipAddress string ) ([]* common.WorkspaceInfo , error ) {
165+ workspaces := make ([]* common.WorkspaceInfo , 0 )
166+
167+ objs , err := r .store .ByIndex (ipAddressIndex , ipAddress )
168+ if err != nil {
169+ return nil , err
170+ }
171+ for _ , w := range objs {
172+ workspaces = append (workspaces , w .(* common.WorkspaceInfo ))
119173 }
120174
121- return nil
175+ return workspaces , nil
122176}
123177
124178func (r * CRDWorkspaceInfoProvider ) AcquireContext (ctx context.Context , workspaceID string , port string ) (context.Context , string , error ) {
0 commit comments