fix(smolmachines): docker push fails on Docker Desktop — daemon-side route differs from host loopback #74
@@ -119,12 +119,20 @@ class Bottle(ABC):
|
|||||||
def exec_claude(self, argv: list[str], *, tty: bool = True) -> int: ...
|
def exec_claude(self, argv: list[str], *, tty: bool = True) -> int: ...
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def exec(self, script: str) -> ExecResult:
|
def exec(self, script: str, *, user: str = "node") -> ExecResult:
|
||||||
"""Run `script` as a POSIX shell script inside the bottle and
|
"""Run `script` as a POSIX shell script inside the bottle as
|
||||||
return the captured stdout/stderr/returncode. The bottle's
|
`user` (default `node`, matching the agent image's USER
|
||||||
environment (including HTTPS_PROXY pointing at the pipelock
|
directive) and return the captured stdout/stderr/returncode.
|
||||||
sidecar) is inherited by the child. Non-zero exit does not
|
The bottle's environment (including HTTPS_PROXY pointing at
|
||||||
raise — callers inspect `returncode` themselves."""
|
the pipelock sidecar) is inherited by the child. Non-zero
|
||||||
|
exit does not raise — callers inspect `returncode`
|
||||||
|
themselves.
|
||||||
|
|
||||||
|
Pass `user="root"` for shell-outs that need privileged file
|
||||||
|
writes / package install — provisioning calls that need root
|
||||||
|
bypass `Bottle.exec` and use the backend-specific raw
|
||||||
|
machine-exec helper, but the tests have a legitimate use
|
||||||
|
case for arbitrary-user runs."""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def cp_in(self, host_path: str, container_path: str) -> None: ...
|
def cp_in(self, host_path: str, container_path: str) -> None: ...
|
||||||
|
|||||||
@@ -51,12 +51,15 @@ class DockerBottle(Bottle):
|
|||||||
self.claude_docker_argv(argv, tty=tty), check=False,
|
self.claude_docker_argv(argv, tty=tty), check=False,
|
||||||
).returncode
|
).returncode
|
||||||
|
|
||||||
def exec(self, script: str) -> ExecResult:
|
def exec(self, script: str, *, user: str = "node") -> ExecResult:
|
||||||
# Pipe via stdin to `sh -s` so the caller never has to worry
|
# Pipe via stdin to `sh -s` so the caller never has to worry
|
||||||
# about quoting; the script source lands inside the container
|
# about quoting; the script source lands inside the container
|
||||||
# without crossing argv.
|
# without crossing argv. `-u <user>` overrides the image's
|
||||||
|
# default USER — defaults to `node` which is already the
|
||||||
|
# image's USER, so the explicit flag is a no-op there but
|
||||||
|
# keeps the cross-backend contract uniform.
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["docker", "exec", "-i", self.name, "sh", "-s"],
|
["docker", "exec", "-u", user, "-i", self.name, "sh", "-s"],
|
||||||
input=script,
|
input=script,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
|
|||||||
@@ -65,15 +65,21 @@ class SmolmachinesBottle(Bottle):
|
|||||||
result = subprocess.run(flags, check=False)
|
result = subprocess.run(flags, check=False)
|
||||||
return result.returncode
|
return result.returncode
|
||||||
|
|
||||||
def exec(self, script: str) -> ExecResult:
|
def exec(self, script: str, *, user: str = "node") -> ExecResult:
|
||||||
"""Run a POSIX shell script as the `node` user and capture
|
"""Run a POSIX shell script as `user` (default `node`) and
|
||||||
the result. Matches the docker backend's `exec`, which
|
capture the result. Matches the docker backend's `exec`,
|
||||||
defaults to the image's USER (also node) — so test
|
which defaults to the image's USER (also node) — so test
|
||||||
helpers / provision shell-outs run with the same identity
|
helpers / provision shell-outs run with the same identity
|
||||||
on both backends."""
|
on both backends. Pass `user="root"` for tests that need
|
||||||
|
root.
|
||||||
|
|
||||||
|
`smolvm machine exec` runs commands as root in the VM, so
|
||||||
|
we always need to switch user (even when the caller asked
|
||||||
|
for root, switching to root is a cheap no-op via
|
||||||
|
`runuser -l root`)."""
|
||||||
r = _smolvm.machine_exec(
|
r = _smolvm.machine_exec(
|
||||||
self.name,
|
self.name,
|
||||||
["runuser", "-l", "node", "-c", script],
|
["runuser", "-l", user, "-c", script],
|
||||||
)
|
)
|
||||||
return ExecResult(
|
return ExecResult(
|
||||||
returncode=r.returncode,
|
returncode=r.returncode,
|
||||||
|
|||||||
Reference in New Issue
Block a user