29c46356ef
Adds the `nested_containers` bottle flag. On the macOS backend it starts a rootless podman service inside the bottle and exposes its Docker-compatible API socket, so the agent still runs `docker` and `docker compose`. No host daemon socket is mounted and the guest gains no capabilities; backends that cannot run a guest-local engine reject the flag in the shared prepare template rather than ignoring it. Podman rather than rootless Docker because Apple Container's capability bounding set omits CAP_SYS_ADMIN, which the kernel requires to write a multi-range uid_map via newuidmap. With no subordinate UID range podman falls back to a single-UID self-mapping an unprivileged process may write itself, so the image build strips /etc/subuid and /etc/subgid entries rather than adding them. That mapping is also why nested containers are not an isolation layer: root inside one is the agent user outside it. They are a build/test convenience; the bottle remains the boundary. Ports the spike branch onto main, renaming docker_access — it implied Docker and granted access to nothing on the host — and drops podman from the derived layer now that every built-in image ships it (#451). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
49 lines
1.3 KiB
Python
49 lines
1.3 KiB
Python
"""Prepare step for the macOS Apple Container backend."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from ...agent_provider import AgentProvisionPlan
|
|
from ...egress import EgressPlan
|
|
from ...env import ResolvedEnv
|
|
from ...git_gate import GitGatePlan
|
|
from ...supervise import SupervisePlan
|
|
from ...manifest import Manifest
|
|
from .. import BottleSpec
|
|
from . import util as container_mod
|
|
from .bottle_plan import MacosContainerBottlePlan
|
|
|
|
|
|
def preflight() -> None:
|
|
container_mod.require_container()
|
|
|
|
|
|
def build_guest_env(resolved_env: ResolvedEnv) -> dict[str, str]:
|
|
return dict(resolved_env.literals)
|
|
|
|
|
|
def resolve_plan(
|
|
spec: BottleSpec,
|
|
manifest: Manifest,
|
|
slug: str,
|
|
resolved_env: ResolvedEnv,
|
|
agent_provision_plan: AgentProvisionPlan,
|
|
egress_plan: EgressPlan,
|
|
supervise_plan: SupervisePlan | None,
|
|
git_gate_plan: GitGatePlan,
|
|
stage_dir: Path,
|
|
) -> MacosContainerBottlePlan:
|
|
return MacosContainerBottlePlan(
|
|
spec=spec,
|
|
manifest=manifest,
|
|
stage_dir=stage_dir,
|
|
slug=slug,
|
|
forwarded_env=dict(resolved_env.forwarded),
|
|
git_gate_plan=git_gate_plan,
|
|
egress_plan=egress_plan,
|
|
supervise_plan=supervise_plan,
|
|
agent_provision=agent_provision_plan,
|
|
nested_containers=manifest.bottle.nested_containers,
|
|
)
|