diff --git a/components/execd/main.go b/components/execd/main.go index f53f198d4..e9b1d7641 100644 --- a/components/execd/main.go +++ b/components/execd/main.go @@ -16,6 +16,7 @@ package main import ( "fmt" + "os" "github.com/alibaba/opensandbox/internal/version" @@ -42,5 +43,6 @@ func main() { log.Info("execd listening on %s", addr) if err := engine.Run(addr); err != nil { log.Error("failed to start execd server: %v", err) + os.Exit(1) } } diff --git a/components/execd/pkg/jupyter/auth/client.go b/components/execd/pkg/jupyter/auth/client.go index d642776d2..bc617235a 100644 --- a/components/execd/pkg/jupyter/auth/client.go +++ b/components/execd/pkg/jupyter/auth/client.go @@ -60,7 +60,7 @@ func (c *Client) Get(url string) (*http.Response, error) { // Post sends a POST request. func (c *Client) Post(url, contentType string, body io.Reader) (*http.Response, error) { - req, err := http.NewRequest(http.MethodPut, url, body) + req, err := http.NewRequest(http.MethodPost, url, body) if err != nil { return nil, err } diff --git a/components/execd/pkg/runtime/command.go b/components/execd/pkg/runtime/command.go index 63c871487..208b541ab 100644 --- a/components/execd/pkg/runtime/command.go +++ b/components/execd/pkg/runtime/command.go @@ -97,6 +97,8 @@ func (c *Controller) runCommand(ctx context.Context, request *ExecuteCodeRequest if err != nil { return fmt.Errorf("failed to get stdlog descriptor: %w", err) } + defer stdout.Close() + defer stderr.Close() stdoutPath := c.stdoutFileName(session) stderrPath := c.stderrFileName(session) @@ -135,6 +137,8 @@ func (c *Controller) runCommand(ctx context.Context, request *ExecuteCodeRequest err = cmd.Start() if err != nil { + close(done) + wg.Wait() request.Hooks.OnExecuteInit(session) request.Hooks.OnExecuteError(&execute.ErrorOutput{EName: "CommandExecError", EValue: err.Error()}) log.Error("CommandExecError: error starting commands: %v", err) @@ -246,7 +250,11 @@ func (c *Controller) runBackgroundCommand(ctx context.Context, cancel context.Ca cmd.Env = mergeEnvs(os.Environ(), extraEnv) // use DevNull as stdin so interactive programs exit immediately. - cmd.Stdin = os.NewFile(uintptr(syscall.Stdin), os.DevNull) + devNull, err := os.Open(os.DevNull) + if err == nil { + cmd.Stdin = devNull + defer devNull.Close() + } err = cmd.Start() kernel := &commandKernel{ diff --git a/components/execd/pkg/runtime/sql.go b/components/execd/pkg/runtime/sql.go index 282476c58..a5aa971b2 100644 --- a/components/execd/pkg/runtime/sql.go +++ b/components/execd/pkg/runtime/sql.go @@ -103,6 +103,10 @@ func (c *Controller) executeSelectSQLQuery(ctx context.Context, request *Execute } result = append(result, row) } + if err := rows.Err(); err != nil { + request.Hooks.OnExecuteError(&execute.ErrorOutput{EName: "RowIterationError", EValue: err.Error()}) + return nil + } queryResult := QueryResult{ Columns: columns, @@ -155,8 +159,11 @@ func (c *Controller) executeUpdateSQLQuery(ctx context.Context, request *Execute // getQueryType extracts the first token to decide which executor to use. func (c *Controller) getQueryType(query string) string { - firstWord := strings.ToUpper(strings.Fields(query)[0]) - return firstWord + fields := strings.Fields(query) + if len(fields) == 0 { + return "" + } + return strings.ToUpper(fields[0]) } // initDB lazily opens the local sandbox database. diff --git a/sdks/code-interpreter/python/src/code_interpreter/adapters/code_adapter.py b/sdks/code-interpreter/python/src/code_interpreter/adapters/code_adapter.py index 4b328c774..069563f4a 100644 --- a/sdks/code-interpreter/python/src/code_interpreter/adapters/code_adapter.py +++ b/sdks/code-interpreter/python/src/code_interpreter/adapters/code_adapter.py @@ -106,6 +106,7 @@ def __init__( headers = { "User-Agent": self.connection_config.user_agent, **self.connection_config.headers, + **self.execd_endpoint.headers, } # Execd API does not require authentication diff --git a/sdks/sandbox/python/src/opensandbox/adapters/converter/sandbox_model_converter.py b/sdks/sandbox/python/src/opensandbox/adapters/converter/sandbox_model_converter.py index 0f6a8c96e..6fc75af6d 100644 --- a/sdks/sandbox/python/src/opensandbox/adapters/converter/sandbox_model_converter.py +++ b/sdks/sandbox/python/src/opensandbox/adapters/converter/sandbox_model_converter.py @@ -90,6 +90,10 @@ def to_api_volume(volume: Volume): from opensandbox.api.lifecycle.models.host import ( Host as ApiHost, ) + from opensandbox.api.lifecycle.models.ossfs import ( + OSSFS as ApiOSSFS, + ) + from opensandbox.api.lifecycle.models.ossfs_version import OSSFSVersion from opensandbox.api.lifecycle.models.pvc import ( PVC as ApiPVC, ) @@ -104,6 +108,17 @@ def to_api_volume(volume: Volume): if volume.pvc is not None: api_pvc = ApiPVC(claim_name=volume.pvc.claim_name) + api_ossfs = UNSET + if volume.ossfs is not None and volume.ossfs.access_key_id is not None and volume.ossfs.access_key_secret is not None: + api_ossfs = ApiOSSFS( + bucket=volume.ossfs.bucket, + endpoint=volume.ossfs.endpoint, + access_key_id=volume.ossfs.access_key_id, + access_key_secret=volume.ossfs.access_key_secret, + version=OSSFSVersion(volume.ossfs.version), + options=volume.ossfs.options if volume.ossfs.options is not None else UNSET, + ) + api_sub_path = UNSET if volume.sub_path is not None: api_sub_path = volume.sub_path @@ -114,6 +129,7 @@ def to_api_volume(volume: Volume): read_only=volume.read_only, host=api_host, pvc=api_pvc, + ossfs=api_ossfs, sub_path=api_sub_path, ) diff --git a/server/src/main.py b/server/src/main.py index bfdff999d..ee6a89b96 100644 --- a/server/src/main.py +++ b/server/src/main.py @@ -106,10 +106,6 @@ async def lifespan(app: FastAPI): k8s_client=k8s_client, ) - # Create sandbox service after validation - from src.services.factory import create_sandbox_service - - app.state.sandbox_service = create_sandbox_service() except Exception as exc: logger.error("Secure runtime validation failed: %s", exc) raise