Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions pkg/k8s/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,15 +213,34 @@ func (c *Client) createPod(ctx context.Context, req *types.StartRequest, runtime
})
}

// Use image ENTRYPOINT (e.g. /openhands/entrypoint.sh for update-ca-certificates)
// and pass request command as Args so the entrypoint receives them as "$@".
// If we set Command we would replace the image ENTRYPOINT and the entrypoint would never run.
// How the request command is turned into a container Command/Args.
//
// OpenHands V1 sends the FULL command in exec form, e.g.
// ["/usr/local/bin/openhands-agent-server", "--port", "60000"]
// The agent-server image ENTRYPOINT is ["tini","--","/usr/local/bin/openhands-agent-server"].
// Passing the full command as Args (the previous behavior) appends it to that ENTRYPOINT, so the
// container runs `tini -- openhands-agent-server /usr/local/bin/openhands-agent-server --port 60000`
// and the agent-server binary receives its own path as a positional arg -> it aborts with
// "unrecognized arguments: /usr/local/bin/openhands-agent-server" and CrashLoops.
//
// Fix: when the command starts with an absolute path (a real binary/exec form, which is what
// OpenHands sends), set it as the container Command so it REPLACES the image ENTRYPOINT and runs
// exactly as given. A single non-path string is still run via `bash -c` (shell form). This keeps
// exec-form commands working with images whose ENTRYPOINT is the target binary (agent-server),
// while preserving shell-string behavior.
var command []string
var args []string
if len(req.Command) > 1 {
switch {
case len(req.Command) > 1 && strings.HasPrefix(req.Command[0], "/"):
// Exec form with an absolute binary path: override ENTRYPOINT, run the command verbatim.
command = []string(req.Command)
args = nil
case len(req.Command) > 1:
// Multi-arg but not an absolute path: treat as args to the image ENTRYPOINT (e.g. a
// shell-wrapper entrypoint that execs "$@" and needs update-ca-certificates to run first).
command = nil
args = []string(req.Command)
} else if len(req.Command) == 1 && req.Command[0] != "" {
case len(req.Command) == 1 && req.Command[0] != "":
// Single string: run via bash -c (no image entrypoint)
command = []string{"/bin/bash", "-c"}
args = []string{req.Command[0]}
Expand Down