use std::time::Duration;
use microvms_core::control::{ControlPlane, EgressPosture, WaitOpts, egress_posture_for, token};
use microvms_core::prelude::*;
use microvms_core::region::Region;
use microvms_core::sandbox::{RunRequest, Sandbox, TeardownOpts};
fn env(name: &str) -> String {
std::env::var(name).unwrap_or_else(|_| panic!("conformance must supply {name}"))
}
fn region() -> Region {
std::env::var("AWS_REGION")
.unwrap_or_else(|_| "us-east-1".into())
.parse()
.expect("a supported region")
}
async fn launch(label: &str, request: RunRequest, failures: &mut Vec<String>) {
let answered = egress_posture_for(
request.egress,
&request.egress_network_connectors,
request.deny_egress,
Some(®ion()),
)
.expect("launchable options");
let token = request.agent_token.clone().expect("an explicit token");
let plane = ControlPlane::new(region()).await.expect("credentials");
let mut sandbox = Sandbox::new(region()).await.expect("credentials");
let launched = sandbox
.run(request)
.await
.map(|session| session.egress_posture());
let record = sandbox
.microvm()
.map(|vm| (vm.id.clone(), vm.endpoint.clone()));
match (&launched, &record) {
(Ok(posture), Some((id, endpoint))) => {
eprintln!("POSTURE {label}={posture} microvmId={id}");
if *posture != answered {
failures.push(format!(
"{label}: the session reports {posture}, egress_posture_for answered {answered}"
));
}
match Sandbox::adopt_in(region(), id, endpoint, &token, None).await {
Ok(adopted) => {
let seen = adopted.session().map(|session| session.egress_posture());
eprintln!(
"POSTURE {label}-adopted={} microvmId={id}",
seen.map_or("none", EgressPosture::as_str)
);
if seen != Some(EgressPosture::Unsealed) {
failures.push(format!("{label}: an adopter reports {seen:?}"));
}
}
Err(error) => failures.push(format!("{label}: adopt failed: {error}")),
}
}
_ => failures.push(format!("{label}: launch failed: {launched:?}")),
}
let _ = sandbox.terminate(TeardownOpts::default()).await;
if let Some((id, _)) = &record {
let opts = WaitOpts {
timeout: Duration::from_secs(120),
poll_interval: Duration::from_secs(2),
..WaitOpts::for_launch()
};
match plane.wait_for_state(id, &["TERMINATED"], &[], opts).await {
Ok(vm) => eprintln!("cleanup microvmId={} state={}", vm.id, vm.state),
Err(error) => failures.push(format!("cleanup unverified for {id}: {error}")),
}
}
}
#[tokio::test]
#[ignore = "needs an explicit conformance image and AWS credentials; launches two bounded VMs"]
async fn a_launched_sessions_posture_is_its_requests() {
let image = env("MICROVM_BACKGROUND_TEST_IMAGE");
let role = env("MICROVM_EXECUTION_ROLE_ARN");
let mut failures = Vec::new();
for (label, egress) in [("default", false), ("egress", true)] {
let mut request = RunRequest::new().with_image(&image);
request.egress = egress;
request.execution_role_arn = Some(role.clone());
request.agent_token = Some(token::run_token("posture-guest"));
request.max_duration_sec = 600;
request.max_idle_sec = 300;
launch(label, request, &mut failures).await;
}
assert!(failures.is_empty(), "{}", failures.join("; "));
}