@@ -11,6 +11,7 @@ import (
1111
1212 "github.com/gin-gonic/gin"
1313 redisv9 "github.com/redis/go-redis/v9"
14+ "k8s.io/client-go/dynamic"
1415 sandboxv1alpha1 "sigs.k8s.io/agent-sandbox/api/v1alpha1"
1516 "sigs.k8s.io/agent-sandbox/controllers"
1617 extensionsv1alpha1 "sigs.k8s.io/agent-sandbox/extensions/api/v1alpha1"
@@ -28,9 +29,27 @@ func (s *Server) handleHealth(c *gin.Context) {
2829
2930// handleCreateSandbox handles sandbox creation requests
3031// nolint :gocyclo
32+ // extractUserK8sClient extracts user information from the context and creates a user-specific Kubernetes client.
33+ // It returns the dynamic client for the user and an error if authentication fails or client creation fails.
34+ func (s * Server ) extractUserK8sClient (c * gin.Context ) (dynamic.Interface , error ) {
35+ // Extract user information from context
36+ userToken , userNamespace , _ , serviceAccountName := extractUserInfo (c )
37+ if userToken == "" || userNamespace == "" || serviceAccountName == "" {
38+ return nil , errors .New ("unable to extract user credentials" )
39+ }
40+
41+ // Create sandbox using user's K8s client
42+ userClient , err := s .k8sClient .GetOrCreateUserK8sClient (userToken , userNamespace , serviceAccountName )
43+ if err != nil {
44+ log .Printf ("create user client failed: %v" , err )
45+ return nil , fmt .Errorf ("create user client failed: %w" , err )
46+ }
47+ return userClient .dynamicClient , nil
48+ }
49+
3150func (s * Server ) handleCreateSandbox (c * gin.Context ) {
32- createAgentRequest := & types.CreateSandboxRequest {}
33- if err := c .ShouldBindJSON (createAgentRequest ); err != nil {
51+ sandboxReq := & types.CreateSandboxRequest {}
52+ if err := c .ShouldBindJSON (sandboxReq ); err != nil {
3453 log .Printf ("parse request body failed: %v" , err )
3554 respondError (c , http .StatusBadRequest , "INVALID_REQUEST" , "Invalid request body" )
3655 return
@@ -39,13 +58,13 @@ func (s *Server) handleCreateSandbox(c *gin.Context) {
3958 reqPath := c .Request .URL .Path
4059 switch {
4160 case strings .HasSuffix (reqPath , "/agent-runtime" ):
42- createAgentRequest .Kind = types .AgentRuntimeKind
61+ sandboxReq .Kind = types .AgentRuntimeKind
4362 case strings .HasSuffix (reqPath , "/code-interpreter" ):
44- createAgentRequest .Kind = types .CodeInterpreterKind
63+ sandboxReq .Kind = types .CodeInterpreterKind
4564 default :
4665 }
4766
48- if err := createAgentRequest .Validate (); err != nil {
67+ if err := sandboxReq .Validate (); err != nil {
4968 log .Printf ("request body validation failed: %v" , err )
5069 respondError (c , http .StatusBadRequest , "INVALID_REQUEST" , err .Error ())
5170 return
@@ -55,14 +74,14 @@ func (s *Server) handleCreateSandbox(c *gin.Context) {
5574 var sandboxClaim * extensionsv1alpha1.SandboxClaim
5675 var externalInfo * sandboxExternalInfo
5776 var err error
58- switch createAgentRequest .Kind {
77+ switch sandboxReq .Kind {
5978 case types .AgentRuntimeKind :
60- sandbox , externalInfo , err = buildSandboxByAgentRuntime (createAgentRequest .Namespace , createAgentRequest .Name , s .informers )
79+ sandbox , externalInfo , err = buildSandboxByAgentRuntime (sandboxReq .Namespace , sandboxReq .Name , s .informers )
6180 case types .CodeInterpreterKind :
62- sandbox , sandboxClaim , externalInfo , err = buildSandboxByCodeInterpreter (createAgentRequest .Namespace , createAgentRequest .Name , s .informers )
81+ sandbox , sandboxClaim , externalInfo , err = buildSandboxByCodeInterpreter (sandboxReq .Namespace , sandboxReq .Name , s .informers )
6382 default :
64- log .Printf ("invalid request kind: %v" , createAgentRequest .Kind )
65- respondError (c , http .StatusBadRequest , "INVALID_REQUEST" , fmt .Sprintf ("invalid request kind: %v" , createAgentRequest .Kind ))
83+ log .Printf ("invalid request kind: %v" , sandboxReq .Kind )
84+ respondError (c , http .StatusBadRequest , "INVALID_REQUEST" , fmt .Sprintf ("invalid request kind: %v" , sandboxReq .Kind ))
6685 return
6786 }
6887
@@ -78,22 +97,12 @@ func (s *Server) handleCreateSandbox(c *gin.Context) {
7897
7998 dynamicClient := s .k8sClient .dynamicClient
8099 if s .config .EnableAuth {
81- // Extract user information from context
82- userToken , userNamespace , _ , serviceAccountName := extractUserInfo (c )
83- if userToken == "" || userNamespace == "" || serviceAccountName == "" {
84- respondError (c , http .StatusUnauthorized , "UNAUTHORIZED" , "Unable to extract user credentials" )
85- return
86- }
87-
88- // Create sandbox using user's K8s client
89- userClient , err := s .k8sClient .GetOrCreateUserK8sClient (userToken , userNamespace , serviceAccountName )
100+ userDynamicClient , err := s .extractUserK8sClient (c )
90101 if err != nil {
91- log .Printf ("create user client failed: %v" , err )
92- respondError (c , http .StatusInternalServerError , "CLIENT_CREATION_FAILED" , err .Error ())
102+ respondError (c , http .StatusUnauthorized , "UNAUTHORIZED" , err .Error ())
93103 return
94104 }
95-
96- dynamicClient = userClient .dynamicClient
105+ dynamicClient = userDynamicClient
97106 }
98107
99108 // CRITICAL: Register watcher BEFORE creating sandbox
@@ -182,7 +191,7 @@ func (s *Server) handleCreateSandbox(c *gin.Context) {
182191 EntryPoints : redisCacheInfo .EntryPoints ,
183192 }
184193
185- if createAgentRequest .Kind != types .CodeInterpreterKind {
194+ if sandboxReq .Kind != types .CodeInterpreterKind {
186195 err = s .redisClient .UpdateSandbox (c .Request .Context (), redisCacheInfo , RedisNoExpiredTTL )
187196 if err != nil {
188197 log .Printf ("update redis cache failed: %v" , err )
@@ -196,9 +205,14 @@ func (s *Server) handleCreateSandbox(c *gin.Context) {
196205 }
197206
198207 if len (redisCacheInfo .EntryPoints ) == 0 {
199- respondError (c , http .StatusInternalServerError , "SANDBOX_INIT_FAILED" ,
200- "No access endpoint found for sandbox initialization" )
201- return
208+ // Fallback to default http://ip:8080
209+ defaultEntryPoint := types.SandboxEntryPoints {
210+ Path : "/" ,
211+ Protocol : "http" ,
212+ Endpoint : fmt .Sprintf ("%s:8080" , podIP ),
213+ }
214+ redisCacheInfo .EntryPoints = []types.SandboxEntryPoints {defaultEntryPoint }
215+ response .EntryPoints = redisCacheInfo .EntryPoints
202216 }
203217
204218 // Code Interpreter sandbox created, init code interpreter
@@ -221,10 +235,10 @@ func (s *Server) handleCreateSandbox(c *gin.Context) {
221235 err = s .InitCodeInterpreterSandbox (
222236 c .Request .Context (),
223237 initEndpoint ,
224- sandbox . Labels [ SessionIdLabelKey ] ,
225- createAgentRequest .PublicKey ,
226- createAgentRequest .Metadata ,
227- createAgentRequest .InitTimeoutSeconds ,
238+ externalInfo . SessionID ,
239+ sandboxReq .PublicKey ,
240+ sandboxReq .Metadata ,
241+ sandboxReq .InitTimeoutSeconds ,
228242 )
229243
230244 if err != nil {
@@ -265,22 +279,12 @@ func (s *Server) handleDeleteSandbox(c *gin.Context) {
265279
266280 dynamicClient := s .k8sClient .dynamicClient
267281 if s .config .EnableAuth {
268- // Extract user information from context
269- userToken , userNamespace , _ , serviceAccountName := extractUserInfo (c )
270-
271- if userToken == "" || userNamespace == "" || serviceAccountName == "" {
272- respondError (c , http .StatusUnauthorized , "UNAUTHORIZED" , "Unable to extract user credentials" )
273- return
274- }
275-
276- // Delete sandbox using user's K8s client
277- userClient , clientErr := s .k8sClient .GetOrCreateUserK8sClient (userToken , userNamespace , serviceAccountName )
278- if clientErr != nil {
279- respondError (c , http .StatusInternalServerError , "CLIENT_CREATION_FAILED" , clientErr .Error ())
282+ userDynamicClient , err := s .extractUserK8sClient (c )
283+ if err != nil {
284+ respondError (c , http .StatusUnauthorized , "UNAUTHORIZED" , err .Error ())
280285 return
281286 }
282-
283- dynamicClient = userClient .dynamicClient
287+ dynamicClient = userDynamicClient
284288 }
285289
286290 if sandbox .Kind == types .SandboxClaimsKind {
0 commit comments