Skip to main content

Sandbox

Struct Sandbox 

Source
pub struct Sandbox { /* private fields */ }
Expand description

One MicroVM’s whole life.

See the module docs for the state machine, the window, and why teardown is explicit.

Implementations§

Source§

impl Sandbox

Source

pub async fn new(region: Region) -> Result<Self, Error>

Resolves credentials for region and returns a sandbox with nothing launched.

TRAP-6 is closed by Region before this is reached, which is why there is no region check here.

Source

pub fn with_control_plane(control: ControlPlane) -> Self

A sandbox over an already-built ControlPlane.

The seam every test uses, and public for the same reason ControlPlane::with_transport is: a caller who wants a non-default port, or a fake transport, has already built the plane, and a sandbox constructible only from a Region would be a sandbox no test can drive without AWS.

The plane’s own clock is what times the suspended window, rather than a second one this type would own. Two clocks in one lifecycle is the trap the daemon’s turmoil tests record: a window measured on one clock while the poll loop sleeps on another calls a closed window open.

Source

pub fn with_session_backend(self, backend: SharedBackend) -> Self

Routes the session Sandbox::run builds through backend instead of real HTTP.

The daemon-side half of the test seam with_control_plane opens: scripting the control plane gets a test through the launch, and this gets it through everything the launched session then does — uploads, execs, downloads — without a daemon.

Source

pub fn lifecycle(&self) -> Lifecycle

The lifecycle state, which is the symspec’s vm_state.

Source

pub fn token_installed(&self) -> bool

Whether the agent token has been installed (STATE-2).

Source

pub fn image_exists(&self) -> bool

Whether an image is recorded as existing (STATE-1).

Source

pub fn was_terminated(&self) -> bool

Whether this VM was ever terminated (STATE-11).

Source

pub fn bootstrap_count(&self) -> u32

How many times the token has been installed. Never above one (STATE-3).

Source

pub fn image(&self) -> Option<&Image>

The image, once built.

Source

pub fn microvm(&self) -> Option<&Microvm>

The VM as the service last described it.

Source

pub fn session(&self) -> Option<&Session>

The session, once launched.

Source

pub fn suspended_window(&self) -> Option<Duration>

The suspended window this sandbox asked for at launch, once it has launched.

Source

pub async fn build_image( &mut self, request: CreateImageRequest, ) -> Result<&Image, Error>

Builds an image and waits for it to become usable.

Every local guard runs inside ControlPlane::create_image, before the call — which matters because the create happens after the caller’s artifact upload, so a rejection AWS raises costs the upload first.

Source

pub fn build_artifact_for( &self, request: &CreateImageRequest, ) -> Result<Vec<u8>, Error>

The artifact bytes to upload to the request’s code_artifact_uri.

The upload is the caller’s: S3 is not in this crate’s dependency set.

Source

pub fn preflight(&self, request: &CreateImageRequest) -> Result<(), Error>

Every local guard Self::build_image runs, callable before the artifact upload.

A delegation to ControlPlane::preflight, on this type so the CLI’s build path reaches it through the one sandbox it already holds. Local; zero calls. The point is ordering: build_image’s guards run after the caller’s upload, so a request this client itself refuses would still cost the S3 PUT unless the caller checks first.

Source

pub async fn resolve_image_arn(&self, identifier: &str) -> Result<String, Error>

The ARN for identifier: an ARN passes through with zero calls, a bare name is resolved through the image listing by exact match.

A read-only delegation to ControlPlane::resolve_image_arn, on this type so the CLI’s launch path reaches it through the one sandbox it already holds. It touches none of the five state-machine variables — resolution is a question about the account, not about this VM’s lifecycle.

Source

pub async fn find_image_by_name( &self, name: &str, ) -> Result<Option<MicrovmImageSummaryWire>, Error>

The image with exactly name, or None. Read-only; see ControlPlane::find_image_by_name for the pagination and exact-match rules.

Source

pub fn artifact_content_hash_for(&self, request: &CreateImageRequest) -> String

The content hash build --reuse keys an image name to. Local; zero calls.

Source

pub async fn managed_base_versions( &self, base_image_arn: &str, ) -> Result<Vec<ManagedMicrovmImageVersionWire>, Error>

The versions of a managed base image, for pinning CreateImageRequest::base_image_version.

A read-only delegation to crate::control::ControlPlane::managed_base_versions, on this type for the reason Self::resolve_image_arn gives: it touches none of the five state-machine variables, because a question about AWS’s published bases is not a question about this VM’s lifecycle.

Source

pub async fn image_version( &self, identifier: &str, version: &str, ) -> Result<MicrovmImageVersionSummaryWire, Error>

One version’s configuration, state, and availability status. Read-only.

Source

pub async fn run(&mut self, request: RunRequest) -> Result<&mut Session, Error>

Launches a MicroVM, waits for RUNNING, and returns its session.

§The three state requirements this is

STATE-1: the accepted launch moves the lifecycle to PENDING and records the image as existing. STATE-2: the platform reporting RUNNING is what marks the token installed — not the launch call, because the run hook is what delivers it and a launch that dies during startup delivered nothing. STATE-3: bootstrap_count is incremented exactly here, and a second run on the same sandbox is refused, which is what makes “at most once per VM lifetime” a property of the type rather than of a caller’s discipline.

The agent token rides in runHookPayload, which is what keeps it out of the shared image snapshot. That is safe because the platform forwards no external traffic until the run hook returns 200, so a per-VM secret delivered at launch wins the first-writer race through the endpoint.

Source

pub async fn suspend(&mut self) -> Result<(), Error>

Freezes the VM and waits for the platform to report it.

A freeze and restore rather than a stop and start: the guest keeps its memory, so the token, the filesystem, and every exec record survive. The one thing that does not is the guest’s view of time — it observes the whole suspension as a single jump, so any timeout, lease, or TLS session a running command holds expires at once on resume.

§STATE-5 is checked before the wire, not after

A suspend from anything but RUNNING is refused here with zero control-plane calls. That is the observable difference between this and a client that lets AWS answer, and it is what the test asserts on.

Source

pub async fn resume(&mut self) -> Result<&mut Session, Error>

Thaws the VM and returns a usable session.

§What is deliberately not re-delivered (STATE-7)

Nothing. No run-hook payload, no token, no bootstrap. The in-memory token survived the freeze, and re-delivering it would hit the daemon’s one-shot bootstrap and be refused — a 409 that reads like a broken VM.

§The window is checked first (STATE-12)

Before any wire call, because the answer is already known and calling costs the poll timeout to learn something worse. The falsification is a service reporting TERMINATED: without this check the resume burns the full deadline and then reports a state the client could have named at once.

§The proxy token is dropped (STATE-8)

Session::rebind invalidates it. The endpoint URL does not change across suspend/resume, so the rebind is usually a no-op on the URL — but a token minted against the pre-suspend instance may no longer validate, and that rejection reads exactly like a dead daemon.

Source

pub async fn terminate(&mut self, opts: TeardownOpts) -> TeardownReport

Tears down, best-effort, never erroring.

Order: VM, then image, then the log group last. The log group is last because the service can recreate a group deleted before its image — and see TeardownReport::undeleted for why this crate names it rather than deleting it.

Trait Implementations§

Source§

impl Debug for Sandbox

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for Sandbox

Warns about a live VM rather than tearing it down.

See the module docs: Drop cannot await, so a teardown here would either deadlock inside a runtime or race the process exit. The warning names the id, because the only useful thing a drop can do is tell whoever reads stderr what to go delete.

eprintln! rather than a log macro because this crate has no logging dependency, and taking one on to warn about a leak would be a dependency for a diagnostic.

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. 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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

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

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

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
Source§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

Source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
Source§

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + 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
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + 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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

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.
Source§

impl<T> WithSubscriber for T

Source§

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
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

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