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
impl Sandbox
Sourcepub async fn new(region: Region) -> Result<Self, Error>
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.
Sourcepub fn with_control_plane(control: ControlPlane) -> Self
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.
Sourcepub fn with_session_backend(self, backend: SharedBackend) -> Self
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.
Sourcepub fn token_installed(&self) -> bool
pub fn token_installed(&self) -> bool
Whether the agent token has been installed (STATE-2).
Sourcepub fn image_exists(&self) -> bool
pub fn image_exists(&self) -> bool
Whether an image is recorded as existing (STATE-1).
Sourcepub fn was_terminated(&self) -> bool
pub fn was_terminated(&self) -> bool
Whether this VM was ever terminated (STATE-11).
Sourcepub fn bootstrap_count(&self) -> u32
pub fn bootstrap_count(&self) -> u32
How many times the token has been installed. Never above one (STATE-3).
Sourcepub fn suspended_window(&self) -> Option<Duration>
pub fn suspended_window(&self) -> Option<Duration>
The suspended window this sandbox asked for at launch, once it has launched.
Sourcepub fn tunnel_identity(&self) -> Option<&TunnelIdentity>
pub fn tunnel_identity(&self) -> Option<&TunnelIdentity>
The tunnel identity, when the launch asked for one (RunRequest::identity).
What tunnel --verify-identity verifies with: the host’s secret and the VM’s public
pin. None on a launch that did not ask, and the tunnel route then refuses an
identity request with close code 4401 rather than downgrading.
Sourcepub fn port(&self) -> u16
pub fn port(&self) -> u16
The agent port the control plane was built with: the hooks port on every image
this sandbox builds, and the port the daemon listens on in every VM it launches.
Read-only; agents::AgentVm needs it to derive a Dockerfile whose AGENTD_PORT
agrees with the launch.
Sourcepub async fn build_image(
&mut self,
request: CreateImageRequest,
) -> Result<&Image, Error>
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.
Sourcepub fn build_artifact_for(
&self,
request: &CreateImageRequest,
) -> Result<Vec<u8>, Error>
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.
Sourcepub fn preflight(&self, request: &CreateImageRequest) -> Result<(), Error>
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.
Sourcepub async fn resolve_image_arn(&self, identifier: &str) -> Result<String, Error>
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.
Sourcepub async fn find_image_by_name(
&self,
name: &str,
) -> Result<Option<MicrovmImageSummaryWire>, Error>
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.
Sourcepub fn artifact_content_hash_for(&self, request: &CreateImageRequest) -> String
pub fn artifact_content_hash_for(&self, request: &CreateImageRequest) -> String
The content hash build --reuse keys an image name to. Local; zero calls.
Sourcepub async fn managed_base_versions(
&self,
base_image_arn: &str,
) -> Result<Vec<ManagedMicrovmImageVersionWire>, Error>
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.
Sourcepub async fn image_version(
&self,
identifier: &str,
version: &str,
) -> Result<MicrovmImageVersionSummaryWire, Error>
pub async fn image_version( &self, identifier: &str, version: &str, ) -> Result<MicrovmImageVersionSummaryWire, Error>
One version’s configuration, state, and availability status. Read-only.
Sourcepub async fn run(&mut self, request: RunRequest) -> Result<&mut Session, Error>
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.
Sourcepub async fn suspend(&mut self) -> Result<(), Error>
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.
Sourcepub async fn resume(&mut self) -> Result<&mut Session, Error>
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.
Sourcepub async fn terminate(&mut self, opts: TeardownOpts) -> TeardownReport
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 Drop for Sandbox
Warns about a live VM rather than tearing it down.
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.
Auto Trait Implementations§
impl !RefUnwindSafe for Sandbox
impl !UnwindSafe for Sandbox
impl Freeze for Sandbox
impl Send for Sandbox
impl Sync for Sandbox
impl Unpin for Sandbox
impl UnsafeUnpin for Sandbox
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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