ContainerManager

Struct ContainerManager 

Source
pub struct ContainerManager {
    inner: Arc<ContainerManagerInner>,
}
Expand description

Shared container manager. Clone-on-Arc; cheap to pass around.

Fields§

§inner: Arc<ContainerManagerInner>

Implementations§

Source§

impl ContainerManager

Source

pub fn connect() -> Result<Self, ContainerError>

Connect to the local Docker daemon using environment/platform defaults.

Honors DOCKER_HOST env var (e.g. for rootless or remote daemons). On Windows connects via named pipe; on macOS/Linux via Unix socket.

Source

pub async fn check_available(&self) -> Result<(), ContainerError>

Ping the Docker daemon. Returns Ok(()) if available.

Source

pub async fn ensure_running( &self, container_name: &str, image: &str, volumes: &[String], env_vars: &[(String, String)], ) -> Result<(), ContainerError>

Ensure the container for this agent is created and running.

  • If it exists and is running: no-op.
  • If it exists but stopped: starts it.
  • If it doesn’t exist: creates and starts it.

Always queries Docker (no in-memory cache) so externally killed containers are detected. Concurrent calls for the same container_name are serialized via a per-container mutex. Concurrent calls for different containers proceed in parallel.

Source

async fn ensure_running_locked( &self, container_name: &str, image: &str, volumes: &[String], env_vars: &[(String, String)], ) -> Result<(), ContainerError>

Create/reuse logic for [ensure_running], run while holding the per-container serialization lock. Split out so ensure_running can wrap it with lock acquisition + map-entry eviction on every exit path.

Source

pub async fn exec( &self, container_name: &str, cmd: &[String], working_dir: Option<&str>, env_vars: &[(String, String)], ) -> Result<ExecSession, ContainerError>

Launch an exec session inside a running container.

Uses -i (not -t) to avoid tty CR/LF corruption of NDJSON output. The caller receives ExecSession whose output stream carries multiplexed stdout/stderr for piping into the block.

Source

pub async fn inspect_exec( &self, exec_id: &str, ) -> Result<Option<i64>, ContainerError>

Retrieve the exit code of a finished exec via the Docker socket.

Returns Ok(Some(code)) once the exec has exited, Ok(None) while it is still running (no code yet) or if Docker did not report one. Call this after the exec’s output stream has ended — unlike a child process’s wait(), the attached output stream closing does not carry the exit status, so the turn’s success/failure can only be known by inspecting.

Source

pub async fn signal_exec_process( &self, container_name: &str, pattern: &str, force: bool, ) -> Result<(), ContainerError>

Best-effort interruption of the turn’s process(es) inside a container.

Docker/bollard has no “kill exec” API, so we pkill the matching process via a short detached exec. The persistent-container model runs one turn at a time (guarded by run_lock), so a single CLI process matches pattern (the command name, e.g. claude). -f matches the full command line because the CLI runs under node, whose process name isn’t the CLI’s.

Requires pkill (procps) in the image. Fire-and-forget (detached); a non-match (pkill exit 1, e.g. the turn already exited) is not an error.

Source

pub async fn stop( &self, container_name: &str, timeout_secs: i64, ) -> Result<(), ContainerError>

Gracefully stop a container. Uses SIGTERM → SIGKILL after timeout_secs.

Source

pub async fn remove( &self, container_name: &str, force: bool, ) -> Result<(), ContainerError>

Remove a container (must be stopped first or use force = true).

Source

async fn find_container( &self, name: &str, ) -> Result<Option<String>, ContainerError>

Returns the container status string (“running”, “exited”, …) or None if not found.

Source

async fn pull_image(&self, image: &str) -> Result<(), ContainerError>

Pull image via the Docker socket (create_image API).

Streams the pull response to completion before returning. If the image is already present locally, Docker returns an empty stream immediately — this function treats that as success (no pull needed).

Errors only on genuine pull failures (network, auth, no such image).

Source

async fn create_and_start( &self, container_name: &str, image: &str, volumes: &[String], env_vars: &[(String, String)], ) -> Result<(), ContainerError>

Trait Implementations§

Source§

impl Clone for ContainerManager

Source§

fn clone(&self) -> ContainerManager

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FromRef<T> for T
where T: Clone,

§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,